<!DOCTYPE html>
<HTML>
<HEAD>
<TITLE>Qi user guide</TITLE>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=iso-8859-1">
<LINK REL="Start" HREF="index.html">
<LINK REL="Contents" HREF="index.html">
<LINK REL="Prev" HREF="configuration.html">
<STYLE TYPE="text/css"><!--
BODY { font-family: serif; }
H1 { font-family: sans-serif; }
H2 { font-family: sans-serif; }
H3 { font-family: sans-serif; }
H4 { font-family: sans-serif; }
H5 { font-family: sans-serif; }
H6 { font-family: sans-serif; }
SUB { font-size: smaller; }
SUP { font-size: smaller; }
PRE { font-family: monospace; margin-left: 36pt; }
--></STYLE>
</HEAD>
<BODY BGCOLOR="white">
<A HREF="index.html">Contents</A>
<A HREF="configuration.html">Previous</A>
<HR NOSHADE>
<center></center>
<h1><a NAME="4">Part IV - Package management</a></h1>

<!-- This user guide is for Qi (version 1.3,
10 Sep 2019), which is a simple but well-integrated package manager.

Copyright (C) 2019 Matias Andres Fonzo, Santiago del Estero,
Argentina.

Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3 or
any later version published by the Free Software Foundation; with no
Invariant Sections, with no Front-Cover Texts, and with no Back-Cover
Texts.  A copy of the license is included in the section entitled
&quot;GNU Free Documentation License&quot;. -->

<!-- Created by GNU Texinfo 6.5, http://www.gnu.org/software/texinfo/ -->
<h1 align="center" class="settitle"><a NAME="5">Qi user guide</a></h1>
 <a name="SEC_Contents"></a>
<h2 class="contents-heading"><a NAME="5_1">Table of Contents</a></h2>
<div class="contents">
<ul class="no-bullet">
<li><a href="#Introduction" name="toc-Introduction-1">1 Introduction</a></li>
<li><a href="#Invoking-qi" name="toc-Invoking-qi-1">2 Invoking qi</a></li>
<li><a href="#The-qirc-file" name="toc-The-qirc-file-1">3 The qirc file</a>
</li>
<li><a href="#Packages" name="toc-Packages-1">4 Packages</a>
<ul class="no-bullet">
<li><a href="#Package-conflicts" name="toc-Package-conflicts">4.1
 Package conflicts</a></li>
<li><a href="#Installing-packages" name="toc-Installing-packages">4.2
 Installing packages</a></li>
<li><a href="#Removing-packages" name="toc-Removing-packages">4.3
 Removing packages</a></li>
<li><a href="#Upgrading-packages" name="toc-Upgrading-packages">4.4
 Upgrading packages</a>
<ul class="no-bullet">
<li><a href="#Package-blacklist" name="toc-Package-blacklist">4.4.1
 Package blacklist</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#Recipes" name="toc-Recipes-1">5 Recipes</a>
<ul class="no-bullet">
<li><a href="#Variables" name="toc-Variables">5.1 Variables</a></li>
<li><a href="#Special-variables" name="toc-Special-variables">5.2
 Special variables</a></li>
<li><a href="#Writing-recipes" name="toc-Writing-recipes">5.3 Writing
 recipes</a></li>
<li><a href="#Building-packages" name="toc-Building-packages">5.4
 Building packages</a></li>
<li><a href="#Variables-from-the-environment" name="toc-Variables-from-the-environment">
5.5 Variables from the environment</a></li>
<li><a href="#The-meta-file" name="toc-The-meta-file">5.6 The meta file</a>
</li>
</ul>
</li>
<li><a href="#Order-files" name="toc-Order-files-1">6 Order files</a></li>
<li><a href="#Creating-packages" name="toc-Creating-packages-1">7
 Creating packages</a></li>
<li><a href="#Examining-packages" name="toc-Examining-packages-1">8
 Examining packages</a></li>
<li><a href="#Exit-status" name="toc-Exit-status-1">9 Exit status</a></li>
<li><a href="#Index" name="toc-Index-1">Index</a></li>
</ul>
</div> <a name="Top"></a><div class="header">
<p> Next: <a accesskey="n" href="#Introduction" rel="next">Introduction</a>
, Up: <a accesskey="u" href="dir.html#Top" rel="up">(dir)</a> &nbsp; [<a href="#SEC_Contents"
rel="contents" title="Table of contents">Contents</a>][<a href="#Index" rel="index"
title="Index">Index</a>]</p>
</div> <a name="SEC_Top"></a>
<p>This user guide is for Qi (version 1.3, 10 Sep 2019).</p>
<table border="0" cellspacing="0" class="menu">
<tr><td align="left" valign="top">&bull; <a accesskey="1" href="#Introduction">
Introduction</a>:</td><td>&nbsp;&nbsp;</td><td align="left" valign="top">
Description and features of qi</td></tr>
<tr><td align="left" valign="top">&bull; <a accesskey="2" href="#Invoking-qi">
Invoking qi</a>:</td><td>&nbsp;&nbsp;</td><td align="left" valign="top">
Command-line options</td></tr>
<tr><td align="left" valign="top">&bull; <a accesskey="3" href="#The-qirc-file">
The qirc file</a>:</td><td>&nbsp;&nbsp;</td><td align="left" valign="top">
Configuration file</td></tr>
<tr><td align="left" valign="top">&bull; <a accesskey="4" href="#Packages">
Packages</a>:</td><td>&nbsp;&nbsp;</td><td align="left" valign="top">Managing
 packages</td></tr>
<tr><td align="left" valign="top">&bull; <a accesskey="5" href="#Recipes">
Recipes</a>:</td><td>&nbsp;&nbsp;</td><td align="left" valign="top">Building
 packages</td></tr>
<tr><td align="left" valign="top">&bull; <a accesskey="6" href="#Order-files">
Order files</a>:</td><td>&nbsp;&nbsp;</td><td align="left" valign="top">Handling
 build order</td></tr>
<tr><td align="left" valign="top">&bull; <a accesskey="7" href="#Creating-packages">
Creating packages</a>:</td><td>&nbsp;&nbsp;</td><td align="left" valign="top">
Making Qi packages</td></tr>
<tr><td align="left" valign="top">&bull; <a accesskey="8" href="#Examining-packages">
Examining packages</a>:</td><td>&nbsp;&nbsp;</td><td align="left" valign="top">
Debugging purposes</td></tr>
<tr><td align="left" valign="top">&bull; <a accesskey="9" href="#Exit-status">
Exit status</a>:</td><td>&nbsp;&nbsp;</td><td align="left" valign="top">Exit codes</td>
</tr>
<tr><td align="left" valign="top">&bull; <a href="#Index">Index</a>:</td><td>
&nbsp;&nbsp;</td><td align="left" valign="top"></td></tr>
</table>
<br>
<p>Copyright (C) 2019 Matias Fonzo.</p>
<p>Qi&rsquo;s home page can be found at <a href="http://www.dragora.org">
http://www.dragora.org</a>. Send&nbsp;bug&nbsp;reports&nbsp;or&nbsp;suggestions&nbsp;to&nbsp;<a href="mailto:dragora-users@nongnu.org">
<span class="nolinebreak">dragora-users</span>@nongnu.org</a>.
<!-- /@w -->
</p>
<hr> <a name="Introduction"></a><div class="header">
<p> Next: <a accesskey="n" href="#Invoking-qi" rel="next">Invoking qi</a>
, Previous: <a accesskey="p" href="#Top" rel="prev">Top</a>, Up: <a accesskey="u"
href="#Top" rel="up">Top</a> &nbsp; [<a href="#SEC_Contents" rel="contents" title="Table of contents">
Contents</a>][<a href="#Index" rel="index" title="Index">Index</a>]</p>
</div> <a name="Introduction-1"></a>
<h2 class="chapter"><a NAME="5_2">1 Introduction</a></h2>
 <a name="index-introduction"></a>
<p>Qi is a simple but well-integrated package manager. It can create,
 install, remove, and upgrade software packages. Qi produces binary
 packages using recipes, which are files containing specific
 instructions to build each package from source. Qi can manage multiple
 packages under a single directory hierarchy. This method allows to
 maintain a set of packages and multiple versions of them. This means
 that Qi could be used as the main package manager or complement the
 existing one.</p>
<p>Qi offers a friendly command line interface, a global configuration
 file, a simple recipe layout to deploy software packages; also works
 with binary packages in parallel, speeding up installations and
 packages in production. The format used for packages is a simplified
 but safe POSIX pax archive compressed with lzip.</p>
<p>Qi is a modern (POSIX-compliant) shell script released under the
 terms of the GNU General Public License. There are only two major
 dependencies for the magic: graft(1) and tarlz(1), the rest is expected
 to be found in any Unix-like system.</p>
<hr> <a name="Invoking-qi"></a><div class="header">
<p> Next: <a accesskey="n" href="#The-qirc-file" rel="next">The qirc
 file</a>, Previous: <a accesskey="p" href="#Introduction" rel="prev">
Introduction</a>, Up: <a accesskey="u" href="#Top" rel="up">Top</a> &nbsp; [<a
href="#SEC_Contents" rel="contents" title="Table of contents">Contents</a>
][<a href="#Index" rel="index" title="Index">Index</a>]</p>
</div> <a name="Invoking-qi-1"></a>
<h2 class="chapter"><a NAME="5_3">2 Invoking qi</a></h2>
 <a name="index-invocation"></a>
<p>This chapter describes the synopsis and command line options for
 invoke Qi.</p>
<div class="example">
<pre class="example">Usage: qi [<var>OPTION</var>]... [<var>FILE</var>]...
</pre>
</div>
<p>One mandatory option specifies the operation that &lsquo;<samp>qi</samp>&rsquo;
 should perform, other options are meant to detail how this operation
 should be performed.</p>
<p>qi supports the following options to operate:</p>
<dl compact="compact">
<dt><code>-b</code></dt>
<dd>
<p>Build package using recipe names.</p>
</dd>
<dt><code>-c</code></dt>
<dd>
<p>Create .tlz package from directory.</p>
</dd>
<dt><code>-d</code></dt>
<dd>
<p>Delete packages.</p>
</dd>
<dt><code>-i</code></dt>
<dd>
<p>Install packages.</p>
</dd>
<dt><code>-o</code></dt>
<dd>
<p>Resolve build order through .order files.</p>
</dd>
<dt><code>-u</code></dt>
<dd>
<p>Update packages (implies -i, -d and -p options).</p>
</dd>
<dt><code>-w</code></dt>
<dd>
<p>Warn about files that will be linked.</p>
</dd>
<dt><code>-x</code></dt>
<dd>
<p>Extract a package for debugging purposes.</p>
</dd>
</dl>
<p>There are common options between modes:</p>
<dl compact="compact">
<dt><code>-N</code></dt>
<dd>
<p>Do not read the configuration file.</p>
<p>This will ignore any value in the qirc file.</p>
</dd>
<dt><code>-P &lt;DIR&gt;</code></dt>
<dd>
<p>Package directory for installations.</p>
<p>This option sets &lsquo;<samp>${packagedir}</samp>&rsquo;.</p>
<p>Only valid for -i, -d, or -u options.</p>
</dd>
<dt><code>-f</code></dt>
<dd>
<p>Force option.</p>
<p>This option can force the build of a recipe, or force the update of a
 pre-existing package.</p>
<p>Only valid for -b, -u options.</p>
</dd>
<dt><code>-t &lt;DIR&gt;</code></dt>
<dd>
<p>Target directory for symbolic links.</p>
<p>This option sets &lsquo;<samp>${targetdir}</samp>&rsquo;.</p>
<p>Only valid for -i, -d, or -u options.</p>
</dd>
<dt><code>-k</code></dt>
<dd>
<p>Keep (don&rsquo;t delete) &lsquo;<samp>${srcdir}</samp>&rsquo; or &lsquo;<samp>${destdir}</samp>
&rsquo; in build mode, keep (don&rsquo;t delete) package directory in delete mode.</p>
<p>Only valid for -b, -d or -u options.</p>
</dd>
<dt><code>-p</code></dt>
<dd>
<p>Prune conflicts on package installations.</p>
<p>This option may proceed with the package installation if one or more
 conflicts occur.</p>
</dd>
<dt><code>-r /rootdir</code></dt>
<dd>
<p>Use the fully qualified named directory as the root directory for all
 qi operations. The target directory and package directory will be
 relative to the specified directory, including the log file for graft.</p>
</dd>
<dt><code>-v</code></dt>
<dd>
<p>Be verbose (a 2nd -v gives more).</p>
</dd>
</dl>
<p>Options for build mode (-b):</p>
<dl compact="compact">
<dt><code>-O &lt;DIR&gt;</code></dt>
<dd>
<p>Where the packages produced are written.</p>
<p>This option sets &lsquo;<samp>${outdir}</samp>&rsquo;.</p>
</dd>
<dt><code>-W &lt;DIR&gt;</code></dt>
<dd>
<p>Where archives, patches, and recipes are expected.</p>
<p>This option sets &lsquo;<samp>${worktree}</samp>&rsquo;.</p>
</dd>
<dt><code>-Z &lt;DIR&gt;</code></dt>
<dd>
<p>Where (compressed) sources will be found.</p>
<p>This option sets &lsquo;<samp>${tardir}</samp>&rsquo;.</p>
</dd>
<dt><code>-a</code></dt>
<dd>
<p>Architecture to use.</p>
<p>Default value is obtained via uname(1) as &lsquo;<samp>uname -m</samp>&rsquo;.</p>
</dd>
<dt><code>-j</code></dt>
<dd>
<p>Parallel jobs for the compiler.</p>
<p>If not specified, default sets to 1.</p>
</dd>
<dt><code>-1</code></dt>
<dd>
<p>Increment release number (&lsquo;<samp>${release}</samp>&rsquo; + 1).</p>
<p>It will be omitted if the -n option is being used.</p>
</dd>
<dt><code>-n</code></dt>
<dd>
<p>Don&rsquo;t create a .tlz package.</p>
</dd>
<dt><code>-S</code></dt>
<dd>
<p>Selects the option to skip completed recipes.</p>
<p>This means, in interactive mode, when the dialog to summarize recipes
 is shown.</p>
</dd>
</dl>
<p>Informative options:</p>
<dl compact="compact">
<dt><code>-L</code></dt>
<dd>
<p>Print default directory locations.</p>
<p>This will print the target directory, package directory, working
 tree, the directory for tarballs, and the output directory for the
 packages produced.</p>
</dd>
<dt><code>-h</code></dt>
<dd>
<p>Display the help describing the options and then exit.</p>
</dd>
<dt><code>-V</code></dt>
<dd>
<p>Print the version number and license information. The version number
 should be included in all bug reports.</p>
</dd>
</dl>
<p>Expected non-option arguments are package directories and regular
 files: recipes or files ending in .tlz, .order. When FILE is -, qi can
 read from the standard input. See examples in <a href="#Packages">
Packages</a>.</p>
<hr> <a name="The-qirc-file"></a><div class="header">
<p> Next: <a accesskey="n" href="#Packages" rel="next">Packages</a>,
 Previous: <a accesskey="p" href="#Invoking-qi" rel="prev">Invoking qi</a>
, Up: <a accesskey="u" href="#Top" rel="up">Top</a> &nbsp; [<a href="#SEC_Contents"
rel="contents" title="Table of contents">Contents</a>][<a href="#Index" rel="index"
title="Index">Index</a>]</p>
</div> <a name="The-qirc-file-1"></a>
<h2 class="chapter"><a NAME="5_4">3 The qirc file</a></h2>
 <a name="index-configuration-file"></a>
<p>The global <samp>qirc</samp> file offers a way to define variables
 and tools (such as a download manager) for default use. This file is
 used by qi at runtime, e.g., to build, install, remove or upgrade
 packages.</p>
<p>It has the following rules:</p>
<ul>
<li> Variables must be declared as &lsquo;<samp>name=value</samp>&rsquo;.</li>
<li> Declaration of values should only take one line, no line break.</li>
<li> For security reasons, assignments like &lsquo;<samp>name=$var</samp>&rsquo; are
 only interpreted as literal.</li>
</ul>
<p>The command line options related to the package directory and target
 directory plus some of the options used for the build mode can override
 some values in <samp>qirc</samp>. See <a href="#Invoking-qi">Invoking
 qi</a>.</p>
<p>The order in which qi looks for this file is:</p>
<ol>
<li> <code>${HOME}/.qirc</code> Effective user.</li>
<li> &lsquo;<samp>${sysconfdir}/qirc</samp>&rsquo; System-wide.</li>
</ol>
<p>If you intend to run qi as effective user, the file &lsquo;<samp>
${sysconfdir}/qirc</samp>&rsquo; could be copied to <code>${HOME}/.qirc</code>
 setting the paths for &lsquo;<samp>${packagedir}</samp>&rsquo; and &lsquo;<samp>
${targetdir}</samp>&rsquo; according to the <code>$HOME</code>.</p>
<hr> <a name="Packages"></a><div class="header">
<p> Next: <a accesskey="n" href="#Recipes" rel="next">Recipes</a>,
 Previous: <a accesskey="p" href="#The-qirc-file" rel="prev">The qirc
 file</a>, Up: <a accesskey="u" href="#Top" rel="up">Top</a> &nbsp; [<a href="#SEC_Contents"
rel="contents" title="Table of contents">Contents</a>][<a href="#Index" rel="index"
title="Index">Index</a>]</p>
</div> <a name="Packages-1"></a>
<h2 class="chapter"><a NAME="5_5">4 Packages</a></h2>
 <a name="index-managing-packages"></a>
<p>A package is a suite of programs usually distributed in binary form
 which may also contain manual pages, documentation, or any other file
 associated to a specific software.</p>
<p>The package format used by qi is a simplified POSIX pax archive
 compressed with lzip. The file extension for packages is &lsquo;<samp>.tlz</samp>
&rsquo;.</p>
<p>Both package installation and package de-installation are managed
 using two important (internal) variables: &lsquo;<samp>${packagedir}</samp>&rsquo;
 and &lsquo;<samp>${targetdir}</samp>&rsquo;, these values can be changed in the
 configuration file or via options.</p>
<p>&lsquo;<samp>${packagedir}</samp>&rsquo; is a common directory tree where the
 package contents will be decompressed (will reside).</p>
<p>&lsquo;<samp>${targetdir}</samp>&rsquo; is a target directory where the links
 will be made by graft(1) taking &lsquo;<samp>${packagedir}/package_name</samp>
&rsquo; into account.</p>
<p>Packages are installed in self-contained directory trees and symbolic
 links from a common area are made to the package files. This allows
 multiple versions of the same package to coexist on the same system.</p>
 <a name="Package-conflicts"></a>
<h3 class="section">4.1 Package conflicts</h3>
 <a name="index-package-conflicts"></a>
<p>All the links to install or remove a package are handled by graft(1).
 Since multiple packages can be installed or removed at the same time,
 certain conflicts may arise between the packages.</p>
<p>graft<a href="#FOOT1" name="DOCF1"><sup>1</sup></a> defines a
 CONFLICT as one of the following conditions:</p>
<ul>
<li> If the package object is a directory and the target object exists
 but is not a directory.</li>
<li> If the package object is not a directory and the target object
 exists and is not a symbolic link.</li>
<li> If the package object is not a directory and the target object
 exists and is a symbolic link to something other than the package
 object.</li>
</ul>
<p>The default behavior of qi for an incoming package is to ABORT if a
 conflict arises. When a package is going to be deleted, qi tells to
 graft(1) to remove those parts that are not in conflict, leaving the
 links to the belonging package. This behavior can be forced if the -p
 option is given.</p>
 <a name="Installing-packages"></a>
<h3 class="section">4.2 Installing packages</h3>
 <a name="index-package-installation"></a>
<p>To install a single package, simply type:</p>
<div class="example">
<pre class="example">qi -i coreutils-8.30-i586+1.tlz
</pre>
</div>
<p>To install multiple packages at once, type:</p>
<div class="example">
<pre class="example">qi -i gcc-8.3.0-i586+1.tlz rafaela-2.2-i586+1.tlz ...
</pre>
</div>
<p>Warn about the files that will be linked:</p>
<div class="example">
<pre class="example">qi -w bash-5.0-i586+1.tlz
</pre>
</div>
<p>This is to verify the content of a package before installing it.</p>
<p>See the process of an installation (very verbose):</p>
<div class="example">
<pre class="example">qi -i -v mariana-3.0-i586+1.tlz
</pre>
</div>
<p>A second -v gives more.</p>
<p>Installing package in a different location:</p>
<div class="example">
<pre class="example">qi -r /media/floppy -i lzip-1.21-i586+1.tlz
</pre>
</div>
<p>The -r option assumes &lsquo;<samp>${targetdir}</samp>&rsquo; and &lsquo;<samp>
${packagedir}</samp>&rsquo;. See:</p>
<div class="example">
<pre class="example">qi -r /home/selk -P /pkgs -t / -i lzip-1.21-i586+1.tlz
</pre>
</div>
<p>In this case the content of &quot;lzip-1.21-i586+1.tlz&quot; will be
 decompressed into &lsquo;<samp>/home/selk/pkgs/lzip-1.21-i586+1</samp>&rsquo;.
 Assuming that the main binary for lzip is under &lsquo;<samp>
/home/selk/pkgs/lzip-1.21-i586+1/usr/bin/</samp>&rsquo; the target for
 &quot;usr/bin&quot; will be created at &lsquo;<samp>/home/selk</samp>&rsquo;. Considering
 that you have exported the <code>PATH</code> as &lsquo;<samp>${HOME}/usr/bin</samp>
&rsquo;, now the system is able to see the recent lzip.</p>
<p>Installing from a list of packages using standard input:</p>
<div class="example">
<pre class="example">cat FILELIST.txt | qi -i -
</pre>
</div>
<p>The list of packages must contain full path names to be passed in the
 installation, e.g.:
 /var/cache/qi/packages/x86_64/devel/tcl-8.6.9-x86_64+1.tlz
 /var/cache/qi/packages/x86_64/devel/tk-8.6.9.1-x86_64+1.tlz
 /var/cache/qi/packages/x86_64/devel/vala-0.42.3-x86_64+1.tlz</p>
 <a name="Removing-packages"></a>
<h3 class="section">4.3 Removing packages</h3>
 <a name="index-package-de_002dinstallation"></a>
<p>To remove a package, simply type:</p>
<div class="example">
<pre class="example">qi -d xz-5.2.4-i586+1.tlz
</pre>
</div>
<p>Delete mode will match the package name using &lsquo;<samp>${packagedir}</samp>
&rsquo; as prefix. For example, if the value of &lsquo;<samp>${packagedir}</samp>&rsquo;
 is set to /usr/local/pkgs, this will be equal to:</p>
<div class="example">
<pre class="example">qi -d /usr/local/pkgs/xz-5.2.4-i586+1
</pre>
</div>
<p>Detailed output (very verbose):</p>
<div class="example">
<pre class="example">qi -d -v /usr/local/pkgs/xz-5.2.4-i586+1
</pre>
</div>
<p>A second -v gives more.</p>
<p>By default the delete mode does not preserve a package directory
 after removing its links from &lsquo;<samp>${targetdir}</samp>&rsquo;, but this
 behavior can be changed if the -k option is passed:</p>
<div class="example">
<pre class="example">qi -d -k /usr/local/pkgs/lzip-1.21-i586+1
</pre>
</div>
<p>This means that the links to the package can be reactivated, later:</p>
<div class="example">
<pre class="example">cd /usr/local/pkgs &amp;&amp; graft -i lzip-1.21-i586+1
</pre>
</div>
<p>Removing package from a different location:</p>
<div class="example">
<pre class="example">qi -r /home/cthulhu -P /pkgs -t / -d xz-5.2.4-i586+1
</pre>
</div>
<p>Removing a package using standard input:</p>
<div class="example">
<pre class="example">echo &quot;vala-0.42.3-x86_64+1&quot; | qi -d -
</pre>
</div>
<p>This will match with the package directory.</p>
 <a name="Upgrading-packages"></a>
<h3 class="section">4.4 Upgrading packages</h3>
 <a name="index-package-upgrade"></a>
<p>The upgrade mode inherits the properties of the installation and
 removal process. To make sure that a package is updated, the package is
 installed in a temporary directory taking &lsquo;<samp>${packagedir}</samp>&rsquo;
 into account. Once the incoming package is pre-installed, qi can
 proceed to search and delete packages that have the same name
 (considered as previous ones). Finally, the package is re-installed at
 its final location and the temporary directory is removed.</p>
<p>To upgrade a package, just type:</p>
<div class="example">
<pre class="example">qi -u gcc-9.0.1-i586+1.tlz
</pre>
</div>
<p>This will proceed to update &quot;gcc-9.0.1-i586+1&quot; removing other
 versions of &quot;gcc&quot; (if any).</p>
<p>If you want to keep the package directories of versions found during
 the upgrade process, just pass:</p>
<div class="example">
<pre class="example">qi -u -k gcc-9.0.1-i586+1.tlz
</pre>
</div>
<p>To see the upgrade process (very verbose):</p>
<div class="example">
<pre class="example">qi -u -v gcc-9.0.1-i586+1.tlz
</pre>
</div>
<p>A second -v gives more.</p>
<p>To force the upgrade of an existing package:</p>
<div class="example">
<pre class="example">qi -u -f gcc-9.0.1-i586+1.tlz
</pre>
</div> <a name="Package-blacklist"></a>
<h4 class="subsection">4.4.1 Package blacklist</h4>
 <a name="index-package-blacklist"></a>
<p>To implement general package facilities, either to install, remove or
 maintain the hierarchy of packages in a clean manner, qi makes use of
 the pruning operation via graft(1):</p>
<p>There is a risk if those are crucial packages for the proper
 functioning of the system, because it implies the deactivation of
 symbolic from the target directory,<em> especially</em> when
 transitioning an incoming package into its final location during
 upgrade.</p>
<p>A blacklist of package names has been devised for the case where a
 user decides to upgrade all packages in the system, or just the crucial
 ones, such as the C library.</p>
<p>The blacklist is related to the upgrade mode only, consists in
 installing a package instead of updating it or removing previous
 versions of it; the content of the package will be updated over the
 existing content at &lsquo;<samp>${packagedir}</samp>&rsquo;, while the existing
 links from &lsquo;<samp>${targetdir}</samp>&rsquo; will be preserved. A pruning of
 links will be carried out in order to re-link possible differences with
 the recent content, this helps to avoid leaving dead links in the
 target directory.</p>
<p>Since the upgrade mode is also used to install a new package, the
 mechanism for blacklist is to install a declared package if it does not
 already exist. If it already exists, it is verified that the binary
 package is newer than the package directory in order to perform an
 update.</p>
<p>Package names for the blacklist can be set from the configuration
 file.</p>
<hr> <a name="Recipes"></a><div class="header">
<p> Next: <a accesskey="n" href="#Order-files" rel="next">Order files</a>
, Previous: <a accesskey="p" href="#Packages" rel="prev">Packages</a>,
 Up: <a accesskey="u" href="#Top" rel="up">Top</a> &nbsp; [<a href="#SEC_Contents"
rel="contents" title="Table of contents">Contents</a>][<a href="#Index" rel="index"
title="Index">Index</a>]</p>
</div> <a name="Recipes-1"></a>
<h2 class="chapter"><a NAME="5_6">5 Recipes</a></h2>
 <a name="index-recipes"></a>
<p>A recipe is a file telling qi what to do. Most often, the recipe
 tells qi how to build a binary package from a source tarball.</p>
<p>A recipe has two parts: a list of variable definitions and a list of
 sections. By convention, the syntax of a section is:</p>
<div class="example">
<pre class="example">section_name()
{
    section lines
}
</pre>
</div>
<p>The section name is followed by parentheses, one newline and an
 opening brace. The line finishing the section contains just a closing
 brace. The section names or the function names currently recognized are
 &lsquo;<samp>build</samp>&rsquo;.</p>
<p>The &lsquo;<samp>build</samp>&rsquo; section is an augmented shell script. This
 is the main section (or<strong> shell function</strong>) which contains
 the instructions to build and produce a package.</p>
 <a name="Variables"></a>
<h3 class="section">5.1 Variables</h3>
 <a name="index-variables"></a>
<p>A &quot;variable&quot; is a<strong> shell variable</strong> defined either in <samp>
qirc</samp> or in a recipe to represent a string of text, called the
 variable&rsquo;s &quot;value&quot;. These values are substituted by explicit request in
 the definitions of other variables or in calls to external commands.</p>
<p>Variables can represent lists of file names, options to pass to
 compilers, programs to run, directories to look in for source files,
 directories to write output to, or anything else you can imagine.</p>
<p>Definitions of variables in qi have four levels of precedence.
 Options which define variables from the command-line override those
 specified in the <samp>qirc</samp> file, while variables defined in the
 recipe override those specified in <samp>qirc</samp>, taking priority
 over those variables set by command-line options. Finally, the
 variables have default values if they are not defined anywhere.</p>
<p>Options that set variables through the command-line can only
 reference variables defined in <samp>qirc</samp> and variables with
 default values.</p>
<p>Definitions of variables in <samp>qirc</samp> can only reference
 variables previously defined in <samp>qirc</samp> and variables with
 default values.</p>
<p>Definitions of variables in the recipe can only reference variables
 set by the command-line, variables previously defined in the recipe,
 variables defined in <samp>qirc</samp>, and variables with default
 values.</p>
 <a name="Special-variables"></a>
<h3 class="section">5.2 Special variables</h3>
 <a name="index-special-variables"></a>
<p>There are variables which can only be set using the command line
 options or via <samp>qirc</samp>, there are other special variables
 which can be defined or redefined in a recipe. See the following
 definitions:</p>
<p>&lsquo;<samp>outdir</samp>&rsquo; is the directory where the packages produced
 are written. This variable can not be redefined in the recipe. Default
 sets to &lsquo;<samp>/var/cache/qi/packages</samp>&rsquo;.</p>
<p>&lsquo;<samp>worktree</samp>&rsquo; is the working tree where archives, patches,
 and recipes are expected. This variable can not be redefined in the
 recipe. Default sets to &lsquo;<samp>/usr/src/qi</samp>&rsquo;.</p>
<p>&lsquo;<samp>tardir</samp>&rsquo; is defined in the recipe to the directory where
 the tarball containing the source can be found. The full name of the
 tarball is composed as &lsquo;<samp>${tardir}/$tarname</samp>&rsquo;. Its value is
 available in the recipe as &lsquo;<samp>${tardir}</samp>&rsquo;; a value of . for &lsquo;<samp>
tardir</samp>&rsquo; sets it to the value of CWD (Current Working Directory),
 this is where the recipe lives.</p>
<p>&lsquo;<samp>arch</samp>&rsquo; is the architecture to compose the package name.
 Its value is available in the recipe as &lsquo;<samp>${arch}</samp>&rsquo;. Default
 value is the output of &lsquo;<samp>uname -m</samp>&rsquo;.</p>
<p>&lsquo;<samp>jobs</samp>&rsquo; is the number of parallel jobs to pass to the
 compiler. Its value is available in the recipe as &lsquo;<samp>${jobs}</samp>
&rsquo;. The default value is 1.</p>
<p>The two variables &lsquo;<samp>${srcdir}</samp>&rsquo; and &lsquo;<samp>${destdir}</samp>
&rsquo; can be set in the recipe, as any other variable, but if they are not,
 qi uses default values for them when building a package.</p>
<p>&lsquo;<samp>srcdir</samp>&rsquo; contains the source code to be compiled, and
 defaults to &lsquo;<samp>${program}-${version}</samp>&rsquo;. &lsquo;<samp>destdir</samp>
&rsquo; is the place where the built package will be installed, and defaults
 to &lsquo;<samp>${TMPDIR}/package-${program}</samp>&rsquo;.</p>
<p>If &lsquo;<samp>pkgname</samp>&rsquo; is left undefined, the special variable &lsquo;<samp>
program</samp>&rsquo; is assigned by default. If &lsquo;<samp>pkgversion</samp>&rsquo; is
 left undefined, the special variable &lsquo;<samp>version</samp>&rsquo; is assigned
 by default.</p>
<p>&lsquo;<samp>pkgname</samp>&rsquo; and &lsquo;<samp>pkgversion</samp>&rsquo; along with: &lsquo;<samp>
version</samp>&rsquo;, &lsquo;<samp>arch</samp>&rsquo;, and &lsquo;<samp>release</samp>&rsquo; are
 used to produce the name of the package in the form: &lsquo;<samp>
${pkgname}-${pkgversion}-${arch}+${release}.tlz</samp>&rsquo;</p>
<p>A special variable called &lsquo;<samp>replace</samp>&rsquo; can be used to
 declare package names that will be replaced at the time of
 installation.</p>
<p>A typical recipe contains the following variables:</p>
<ul>
<li> &lsquo;<samp>program</samp>&rsquo;: software name.
<p>It matches the source name. It is also used to compose the name of
 the package if &lsquo;<samp>${pkgname}</samp>&rsquo; is not specified.</p>
</li>
<li> &lsquo;<samp>version</samp>&rsquo;: software version.
<p>It matches the source name. It is also used to compose the version of
 the package if &lsquo;<samp>${pkgversion}</samp>&rsquo; is not specified.</p>
</li>
<li> &lsquo;<samp>arch</samp>&rsquo;: software architecture.
<p>It is used to compose the architecture of the package in which it is
 build.</p>
</li>
<li> &lsquo;<samp>release</samp>&rsquo;: release number.
<p>This is used to reflect the release number of the package. It is
 recommended to increase this number after any significant change in the
 recipe or post-install script.</p>
</li>
</ul>
<p>Obtaining sources over the network must be declared in the recipe
 using the &lsquo;<samp>fetch</samp>&rsquo; variable. Use double quotes for
 separated values.</p>
<p>The variables &lsquo;<samp>netget</samp>&rsquo; and &lsquo;<samp>rsync</samp>&rsquo; can be
 defined in <samp>qirc</samp> to establish a network downloader in order
 to get the sources. If they are not defined, qi uses default values:</p>
<p>&lsquo;<samp>netget</samp>&rsquo; is the general network downloader tool,
 defaults sets to &lsquo;<samp>wget -c -w1 -t3 --no-check-certificate</samp>&rsquo;.</p>
<p>&lsquo;<samp>rsync</samp>&rsquo; is the network tool for sources containing the
 prefix for the RSYNC protocol, default sets to &lsquo;<samp>rsync -v -a -L -z
 -i --progress</samp>&rsquo;.</p>
<p>The variable &lsquo;<samp>description</samp>&rsquo; is used to print the package
 description when a package is installed.</p>
<p>A description has two parts: a brief description, and a long
 description. By convention, the syntax of &lsquo;<samp>description</samp>&rsquo;
 is:</p>
<div class="example">
<pre class="example">description=&quot;
Brief description.

Long description.
&quot;
</pre>
</div>
<p>The first line of the value represented is a brief description of the
 software (called &quot;blurb&quot;). A blank line separates the<em> brief
 description</em> from the<em> long description</em>, which should
 contain a more descriptive description of the software.</p>
<p>An example looks like:</p>
<div class="example">
<pre class="example">description=&quot;
The GNU core utilities.

The GNU core utilities are the basic file, shell and text manipulation
utilities of the GNU operating system.  These are the core utilities
which are expected to exist on every operating system.
&quot;
</pre>
</div>
<p>Please consider a length limit of 78 characters as maximum, because
 the same one would be used on the meta file creation. See <a href="#Recipes">
The meta file</a> section.</p>
<p>The &lsquo;<samp>homepage</samp>&rsquo; variable is used to declare the main site
 or home page:</p>
<div class="example">
<pre class="example">homepage=http://www.gnu.org/software/gcc
</pre>
</div>
<p>The variable &lsquo;<samp>license</samp>&rsquo; is used for license information<a href="#FOOT2"
name="DOCF2"><sup>2</sup></a>. Some code in the program can be covered
 by license A, license B, or license C. For &quot;separate licensing&quot; or
 &quot;heterogeneous licensing&quot;, we suggest using<strong> |</strong> for a
 disjunction,<strong> &amp;</strong> for a conjunction (if that ever happens
 in a significant way), and comma for heterogeneous licensing. Comma
 would have lower precedence, plus added special terms.</p>
<div class="example">
<pre class="example">license=&quot;LGPL, GPL | Artistic + added permission&quot;
</pre>
</div> <a name="Writing-recipes"></a>
<h3 class="section">5.3 Writing recipes</h3>
 <a name="index-writing-recipes"></a>
<p>Originally, qi was designed for the version 3 of Dragora GNU/Linux
 (this does not mean that you can&rsquo;t use it in another distribution, just
 that if you do you will need to test it for your selves). To aid this
 here are some references to well written recipes:</p>
<p><a href="http://git.savannah.nongnu.org/cgit/dragora.git/tree/recipes">
http://git.savannah.nongnu.org/cgit/dragora.git/tree/recipes</a>. <a href="http://notabug.org/dragora/dragora/src/master/recipes">
http://notabug.org/dragora/dragora/src/master/recipes</a>.</p>
<p>You can also check the &quot;doc&quot; directory in the distribution sources of
 qi for some examples.</p>
 <a name="Building-packages"></a>
<h3 class="section">5.4 Building packages</h3>
 <a name="index-package-build"></a>
<p>A recipe is any valid regular file. Qi sets priorities for reading a
 recipe, the order in which qi looks for a recipe is:</p>
<ol>
<li> Current working directory.</li>
<li> If the specified path name does not contain &quot;recipe&quot; as the last
 component. Qi will complete it by adding &quot;recipe&quot; to the path name.</li>
<li> If the recipe is not in the current working directory, it will be
 searched under &lsquo;<samp>${worktree}/recipes</samp>&rsquo;. The last component
 will be completed adding &quot;recipe&quot; to the specified path name.</li>
</ol>
<p>To build a single package, type:</p>
<div class="example">
<pre class="example">qi -b x-apps/xterm
</pre>
</div>
<p>Multiple jobs can be passed to the compiler to speed up the build
 process:</p>
<div class="example">
<pre class="example">qi -b -j3 x-apps/xterm
</pre>
</div>
<p>Update or install the package produced (if it is not already
 installed) when finish:</p>
<div class="example">
<pre class="example">qi -b -j3 -u x-apps/xterm
</pre>
</div>
<p>Only process a recipe but do not create the binary package:</p>
<div class="example">
<pre class="example">qi -b -n dict/aspell
</pre>
</div>
<p>The options -i or -u have no effect when -n is given.</p>
<p>This can be useful to inspect the build process of recipe:</p>
<p>qi -b -k -n dict/aspell 2&gt;&amp;1 | tee aspell-buildlog.txt</p>
<p>The -k option could preserve the source directory and the destination
 directory for later inspection. A log file of the build process will be
 created redirecting both, standard error and standard output to tee(1).</p>
 <a name="Variables-from-the-environment"></a>
<h3 class="section">5.5 Variables from the environment</h3>
 <a name="index-environment-variables"></a>
<p>Qi has environment variables which can be used at build time:</p>
<p>The variable <code>TMPDIR</code> sets the temporary directory for
 sources, which is used for package extractions (see <a href="#Examining-packages">
Examining packages</a>) and is prepended to the value of &lsquo;<samp>
${srcdir}</samp>&rsquo; and &lsquo;<samp>${destdir}</samp>&rsquo; in build mode. By
 convention its default value is equal to &lsquo;<samp>/usr/src/qi/build</samp>
&rsquo;.</p>
<p>The variables <code>QICFLAGS</code>, <code>QICXXFLAGS</code>, and <code>
QILDFLAGS</code> have no effect by default. The environment variables
 such as <code>CFLAGS</code>, <code>CXXFLAGS</code>, and <code>LDFLAGS</code>
 are unset at compile time:</p>
<p>Recommended practice is to set variables in the command line of &lsquo;<samp>
configure</samp>&rsquo; or<em> make(1)</em> instead of exporting to the
 environment. As follows:</p>
<blockquote>
<p>Variables not defined in a site shell script can be set in the
 environment passed to configure. However, some packages may run
 configure again during the build, and the customized values of these
 variables may be lost. In order to avoid this problem, you should set
 them in the configure command line, using &lsquo;<samp>VAR=value</samp>&rsquo;. For
 example:</p>
<p><code>./configure CC=/usr/local2/bin/gcc</code></p>
<p><a href="http://gnu.org/savannah-checkouts/gnu/autoconf/manual/autoconf-2.69/html_node/Defining-Variables.html">
http://gnu.org/savannah-checkouts/gnu/autoconf/manual/autoconf-2.69/html_node/Defining-Variables.html
</a></p>
</blockquote><blockquote>
<p>Indeed, while configure can notice the definition of CC in &lsquo;<samp>
./configure CC=bizarre-cc</samp>&rsquo;, it is impossible to notice it in &lsquo;<samp>
CC=bizarre-cc ./configure</samp>&rsquo;, which, unfortunately, is what most
 users do.</p>
<p>[...]</p>
<p>configure: error: changes in the environment can compromise the
 build.</p>
<p><a href="http://gnu.org/savannah-checkouts/gnu/autoconf/manual/autoconf-2.69/html_node/Setting-Output-Variables.html">
http://gnu.org/savannah-checkouts/gnu/autoconf/manual/autoconf-2.69/html_node/Setting-Output-Variables.html
</a></p>
</blockquote><blockquote>
<p>It is not wise for makefiles to depend for their functioning on
 environment variables set up outside their control, since this would
 cause different users to get different results from the same makefile.
 This is against the whole purpose of most makefiles.</p>
<p><a href="http://gnu.org/software/make/manual/make.html#Environment">
http://gnu.org/software/make/manual/make.html#Environment</a></p>
</blockquote> <a name="The-meta-file"></a>
<h3 class="section">5.6 The meta file</h3>
 <a name="index-the-meta-file"></a>
<p>The &quot;meta file&quot; is a regular file created during the build mode, it
 contains information about the package such as package name, package
 version, architecture, release, fetch address, description, and other
 minor data extracted from processed recipes. The name of the file is
 generated as &lsquo;<samp>${full_pkgname}.tlz.txt</samp>&rsquo;, and its purpose is
 to reflect essential information to the user without having to look
 inside the package content. The file format is also intended to be
 imported from other scripts.</p>
<p>The content of a meta file looks like:</p>
<div class="example">
<pre class="example">#
# The Bourne Again SHell.
#
# Bash is an sh-compatible shell that incorporates useful features from
# the Korn shell (ksh) and C shell (csh).  It is intended to conform to
# the IEEE POSIX P1003.2/ISO 9945.2 shell and tools standard.
#
# It offers functional improvements over sh for both programming and
# interactive use.
#

QICFLAGS=&quot;-g0 -Os -mtune=generic -pipe&quot;
QICXXFLAGS=&quot;-g0 -Os -mtune=generic -pipe&quot;
QILDFLAGS=&quot;-s&quot;
pkgname=bash
pkgversion=5.0
arch=x86_64
release=1
blurb=&quot;The Bourne Again SHell.&quot;
homepage=&quot;http://www.gnu.org/software/bash&quot;
license=&quot;GPLv3+&quot;
fetch=&quot;ftp://ftp.gnu.org/gnu/bash/bash-5.0.tar.gz&quot;
replace=&quot;&quot;
</pre>
</div>
<p>Package descriptions are extracted from the variable &lsquo;<samp>
description</samp>&rsquo; where each line is interpreted literally and
 pre-formatted to fit in (exactly)<strong> 80 columns</strong>, plus the
 character &lsquo;<samp>#</samp>&rsquo; and a space is prefixed to every line.</p>
<p>In addition to the Special variables, there are implicit variables
 such as &lsquo;<samp>blurb</samp>&rsquo;:</p>
<p>The &lsquo;<samp>blurb</samp>&rsquo; variable is related to the special variable
 &lsquo;<samp>description</samp>&rsquo;. Its value is composed using the first
 (substantial) line of &lsquo;<samp>description</samp>&rsquo;, mentioned as the
 &quot;brief description&quot;.</p>
<hr> <a name="Order-files"></a><div class="header">
<p> Next: <a accesskey="n" href="#Creating-packages" rel="next">Creating
 packages</a>, Previous: <a accesskey="p" href="#Recipes" rel="prev">
Recipes</a>, Up: <a accesskey="u" href="#Top" rel="up">Top</a> &nbsp; [<a href="#SEC_Contents"
rel="contents" title="Table of contents">Contents</a>][<a href="#Index" rel="index"
title="Index">Index</a>]</p>
</div> <a name="Order-files-1"></a>
<h2 class="chapter"><a NAME="5_7">6 Order files</a></h2>
 <a name="index-handling-build-order"></a>
<p>The order mode has the purpose of resolving the build order through
 .order files. An order file contains a list of recipe names, by default
 does not perform any action other than to print a resolved list in
 descending order. For example, if<strong> a</strong> depends on<strong>
 b</strong> and<strong> c</strong>, and<strong> c</strong> depends on<strong>
 b</strong> as well, the file might look like:</p>
<div class="example">
<pre class="example">a: c b
b:
c: b
</pre>
</div>
<p>Each letter represents a recipe name, complete dependencies for the
 first recipe name are listed in descending order, which is printed from
 right to left, and removed from left to right:</p>
<p><small>OUTPUT</small></p>
<div class="example">
<pre class="example">b
c
a
</pre>
</div>
<p>Blank lines, colons and parentheses are simply ignored. Comment lines
 beginning with &lsquo;<samp>#</samp>&rsquo; are allowed.</p>
<p>An order file could be used to build a series of packages, for
 example, if the content is:</p>
<div class="example">
<pre class="example"># Image handling libraries

libs/libjpeg-turbo: devel/nasm
x-libs/jasper: libs/libjpeg-turbo
libs/tiff: libs/libjpeg-turbo
</pre>
</div>
<p>To proceed with each recipe, we can type:</p>
<div class="example">
<pre class="example">qi -o imglibs.order | qi -b -i -
</pre>
</div>
<p>The output of &lsquo;<samp>qi -o imglibs.order</samp>&rsquo; tells to qi in which
 order it should build the recipes:</p>
<div class="example">
<pre class="example">devel/nasm
libs/libjpeg-turbo
x-libs/jasper
libs/tiff
</pre>
</div>
<hr> <a name="Creating-packages"></a><div class="header">
<p> Next: <a accesskey="n" href="#Examining-packages" rel="next">
Examining packages</a>, Previous: <a accesskey="p" href="#Order-files" rel="prev">
Order files</a>, Up: <a accesskey="u" href="#Top" rel="up">Top</a> &nbsp; [<a href="#SEC_Contents"
rel="contents" title="Table of contents">Contents</a>][<a href="#Index" rel="index"
title="Index">Index</a>]</p>
</div> <a name="Creating-packages-1"></a>
<h2 class="chapter"><a NAME="5_8">7 Creating packages</a></h2>
 <a name="index-package-creation"></a>
<p>The &quot;creation mode&quot; is an internal function of qi to make new Qi
 compatible compatible packages, the creation mode is selected by the -c
 option. A package is produced using the contents of the Current
 Directory, and the package file is written out.</p>
<div class="example">
<pre class="example">Usage: qi -c [<var>OUTPUT/packagename.tlz</var>]...
</pre>
</div>
<p>The argument for the file name to be written must contain a fully
 qualified named directory as the output directory where the package
 produced will be written. The file name should be composed using the
 full name: name-version-architecture+release.tlz</p>
<p><small>EXAMPLE</small></p>
<div class="example">
<pre class="example">cd /usr/local/pkgs
cd claws-mail-3.17.1-x86_64+1
qi -c /var/cache/qi/packages/x86_64/local/claws-mail-3.17.1-x86_64+1.tlz
</pre>
</div>
<p>In this case, the package &quot;claws-mail-3.17.1-x86_64+1.tlz&quot; will be
 written into &lsquo;<samp>/var/cache/qi/packages/x86_64/local/</samp>&rsquo;.</p>
<p>All packages produced are complemented by a checksum file (.sha256).</p>
<hr> <a name="Examining-packages"></a><div class="header">
<p> Next: <a accesskey="n" href="#Exit-status" rel="next">Exit status</a>
, Previous: <a accesskey="p" href="#Creating-packages" rel="prev">
Creating packages</a>, Up: <a accesskey="u" href="#Top" rel="up">Top</a>
 &nbsp; [<a href="#SEC_Contents" rel="contents" title="Table of contents">
Contents</a>][<a href="#Index" rel="index" title="Index">Index</a>]</p>
</div> <a name="Examining-packages-1"></a>
<h2 class="chapter"><a NAME="5_9">8 Examining packages</a></h2>
 <a name="index-package-examination"></a>
<p>The &quot;extraction mode&quot; serves to examine binary packages for debugging
 purposes. The extraction mode is selected by the -x option. It
 decompresses a package into a single directory, verifying its integrity
 and preserving its properties.</p>
<div class="example">
<pre class="example">Usage: qi -x [<var>packagename.tlz</var>]...
</pre>
</div>
<p><small>EXAMPLE</small></p>
<div class="example">
<pre class="example">qi -x mksh-R56c-x86_64+1.tlz
</pre>
</div>
<p>This action will put the content of &quot;mksh-R56c-x86_64+1.tlz&quot; into a
 single directory, this will be a private directory for the user who</p>
<p>requested the action, creation mode will be equal to<strong>
 u=rwx,g=,o= (0700)</strong>. The package content will reside on this
 location, default mask to deploy the content will be equal to<strong>
 u=rwx,g=rwx,o=rwx (0000)</strong>.</p>
<p>The creation of the custom directory is influenced by the value of
 the <code>TMPDIR</code> variable.</p>
<hr> <a name="Exit-status"></a><div class="header">
<p> Next: <a accesskey="n" href="#Index" rel="next">Index</a>, Previous:
 <a accesskey="p" href="#Examining-packages" rel="prev">Examining
 packages</a>, Up: <a accesskey="u" href="#Top" rel="up">Top</a> &nbsp; [<a href="#SEC_Contents"
rel="contents" title="Table of contents">Contents</a>][<a href="#Index" rel="index"
title="Index">Index</a>]</p>
</div> <a name="Exit-status-1"></a>
<h2 class="chapter"><a NAME="5_10">9 Exit status</a></h2>
 <a name="index-exit-codes"></a>
<p>All the exit codes are described in this chapter.</p>
<dl compact="compact">
<dt>&lsquo;<samp>0</samp>&rsquo;</dt>
<dd>
<p>Successful completion (no errors).</p>
</dd>
<dt>&lsquo;<samp>1</samp>&rsquo;</dt>
<dd>
<p>Minor common errors:</p>
<ul class="no-bullet">
<li>- Help usage on illegal options or required arguments.</li>
<li>- Program needed by qi (prerequisite) is not available.</li>
</ul>
</dd>
<dt>&lsquo;<samp>2</samp>&rsquo;</dt>
<dd>
<p>Command execution error:</p>
<p>This code is used to return the evaluation of external commands and
 shell arguments in case of error.</p>
</dd>
<dt>&lsquo;<samp>3</samp>&rsquo;</dt>
<dd>
<p>Integrity check error for compressed files.</p>
<p>Compressed files means:</p>
<ul class="no-bullet">
<li>- Tarball files from tar(1). Supported extensions: .tar, .tar.gz,
 .tgz, .tar.Z, .tar.bz2, .tbz2, .tbz, .tar.xz, .txz</li>
<li>- Tarball files from tarlz(1). Supported extensions: .tar.lz, .tlz</li>
<li>- Zip files from unzip(1). Supported extensions: .zip, .ZIP</li>
<li>- Gzip files from gzip(1). Supported extensions: .gz, .Z</li>
<li>- Bzip2 files from bzip2(1). Supported extensions: .bz2</li>
<li>- Lzip files from lzip(1). Supported extensions: .lz</li>
<li>- Xz files from xz(1). Supported extensions: .xz</li>
</ul>
</dd>
<dt>&lsquo;<samp>4</samp>&rsquo;</dt>
<dd>
<p>File empty, not regular, or expected.</p>
<p>Commonly, it is expected:</p>
<ul class="no-bullet">
<li>- An argument for the mode of operation.</li>
<li>- A readable file or directory.</li>
<li>- A binary package (.tlz).</li>
<li>- A valid recipe.</li>
<li>- An order file (.order).</li>
<li>- A protocol supported by the network downloader tool.</li>
<li>- A checksum file (.sha256).</li>
</ul>
</dd>
<dt>&lsquo;<samp>5</samp>&rsquo;</dt>
<dd>
<p>Empty or not defined variable:</p>
<p>This code is used to report empty or undefined variables; usually,
 variables coming from a recipe or assigned arrays that are tested.</p>
</dd>
<dt>&lsquo;<samp>6</samp>&rsquo;</dt>
<dd>
<p>Package already installed:</p>
<p>The package directory for an incoming .tlz package already exists.</p>
</dd>
<dt>&lsquo;<samp>10</samp>&rsquo;</dt>
<dd>
<p>Network manager error:</p>
<p>This code is used if the network downloader tool fails for some
 reason.</p>
</dd>
</dl>
<hr> <a name="Index"></a><div class="header">
<p> Previous: <a accesskey="p" href="#Exit-status" rel="prev">Exit
 status</a>, Up: <a accesskey="u" href="#Top" rel="up">Top</a> &nbsp; [<a href="#SEC_Contents"
rel="contents" title="Table of contents">Contents</a>][<a href="#Index" rel="index"
title="Index">Index</a>]</p>
</div> <a name="Index-1"></a>
<h2 class="unnumbered"><a NAME="5_11">Index</a></h2>
<table>
<tr><th valign="top">Jump to: &nbsp;</th><td><a class="summary-letter" href="#Index_cp_letter-C">
<b>C</b></a> &nbsp; <a class="summary-letter" href="#Index_cp_letter-E"><b>E</b>
</a> &nbsp; <a class="summary-letter" href="#Index_cp_letter-H"><b>H</b></a>
 &nbsp; <a class="summary-letter" href="#Index_cp_letter-I"><b>I</b></a> &nbsp; <a class="summary-letter"
href="#Index_cp_letter-M"><b>M</b></a> &nbsp; <a class="summary-letter" href="#Index_cp_letter-P">
<b>P</b></a> &nbsp; <a class="summary-letter" href="#Index_cp_letter-R"><b>R</b>
</a> &nbsp; <a class="summary-letter" href="#Index_cp_letter-S"><b>S</b></a>
 &nbsp; <a class="summary-letter" href="#Index_cp_letter-T"><b>T</b></a> &nbsp; <a class="summary-letter"
href="#Index_cp_letter-V"><b>V</b></a> &nbsp; <a class="summary-letter" href="#Index_cp_letter-W">
<b>W</b></a> &nbsp;</td></tr>
</table>
<table border="0" class="index-cp">
<tr><td></td><th align="left">Index Entry</th><td>&nbsp;</td><th align="left">
 Section</th></tr>
<tr><td colspan="4">
<hr></td></tr>
<tr><th><a name="Index_cp_letter-C">C</a></th><td></td><td></td></tr>
<tr><td></td><td valign="top"><a href="#index-configuration-file">
configuration file</a>:</td><td>&nbsp;</td><td valign="top"><a href="#The-qirc-file">
The qirc file</a></td></tr>
<tr><td colspan="4">
<hr></td></tr>
<tr><th><a name="Index_cp_letter-E">E</a></th><td></td><td></td></tr>
<tr><td></td><td valign="top"><a href="#index-environment-variables">
environment variables</a>:</td><td>&nbsp;</td><td valign="top"><a href="#Recipes">
Recipes</a></td></tr>
<tr><td></td><td valign="top"><a href="#index-exit-codes">exit codes</a>
:</td><td>&nbsp;</td><td valign="top"><a href="#Exit-status">Exit status</a></td>
</tr>
<tr><td colspan="4">
<hr></td></tr>
<tr><th><a name="Index_cp_letter-H">H</a></th><td></td><td></td></tr>
<tr><td></td><td valign="top"><a href="#index-handling-build-order">
handling build order</a>:</td><td>&nbsp;</td><td valign="top"><a href="#Order-files">
Order files</a></td></tr>
<tr><td colspan="4">
<hr></td></tr>
<tr><th><a name="Index_cp_letter-I">I</a></th><td></td><td></td></tr>
<tr><td></td><td valign="top"><a href="#index-introduction">introduction</a>
:</td><td>&nbsp;</td><td valign="top"><a href="#Introduction">Introduction</a>
</td></tr>
<tr><td></td><td valign="top"><a href="#index-invocation">invocation</a>
:</td><td>&nbsp;</td><td valign="top"><a href="#Invoking-qi">Invoking qi</a></td>
</tr>
<tr><td colspan="4">
<hr></td></tr>
<tr><th><a name="Index_cp_letter-M">M</a></th><td></td><td></td></tr>
<tr><td></td><td valign="top"><a href="#index-managing-packages">
managing packages</a>:</td><td>&nbsp;</td><td valign="top"><a href="#Packages">
Packages</a></td></tr>
<tr><td colspan="4">
<hr></td></tr>
<tr><th><a name="Index_cp_letter-P">P</a></th><td></td><td></td></tr>
<tr><td></td><td valign="top"><a href="#index-package-blacklist">package
 blacklist</a>:</td><td>&nbsp;</td><td valign="top"><a href="#Packages">
Packages</a></td></tr>
<tr><td></td><td valign="top"><a href="#index-package-build">package
 build</a>:</td><td>&nbsp;</td><td valign="top"><a href="#Recipes">Recipes</a>
</td></tr>
<tr><td></td><td valign="top"><a href="#index-package-conflicts">package
 conflicts</a>:</td><td>&nbsp;</td><td valign="top"><a href="#Packages">
Packages</a></td></tr>
<tr><td></td><td valign="top"><a href="#index-package-creation">package
 creation</a>:</td><td>&nbsp;</td><td valign="top"><a href="#Creating-packages">
Creating packages</a></td></tr>
<tr><td></td><td valign="top"><a href="#index-package-de_002dinstallation">
package de-installation</a>:</td><td>&nbsp;</td><td valign="top"><a href="#Packages">
Packages</a></td></tr>
<tr><td></td><td valign="top"><a href="#index-package-examination">
package examination</a>:</td><td>&nbsp;</td><td valign="top"><a href="#Examining-packages">
Examining packages</a></td></tr>
<tr><td></td><td valign="top"><a href="#index-package-installation">
package installation</a>:</td><td>&nbsp;</td><td valign="top"><a href="#Packages">
Packages</a></td></tr>
<tr><td></td><td valign="top"><a href="#index-package-upgrade">package
 upgrade</a>:</td><td>&nbsp;</td><td valign="top"><a href="#Packages">
Packages</a></td></tr>
<tr><td colspan="4">
<hr></td></tr>
<tr><th><a name="Index_cp_letter-R">R</a></th><td></td><td></td></tr>
<tr><td></td><td valign="top"><a href="#index-recipes">recipes</a>:</td><td>
&nbsp;</td><td valign="top"><a href="#Recipes">Recipes</a></td></tr>
<tr><td colspan="4">
<hr></td></tr>
<tr><th><a name="Index_cp_letter-S">S</a></th><td></td><td></td></tr>
<tr><td></td><td valign="top"><a href="#index-special-variables">special
 variables</a>:</td><td>&nbsp;</td><td valign="top"><a href="#Recipes">
Recipes</a></td></tr>
<tr><td colspan="4">
<hr></td></tr>
<tr><th><a name="Index_cp_letter-T">T</a></th><td></td><td></td></tr>
<tr><td></td><td valign="top"><a href="#index-the-meta-file">the meta
 file</a>:</td><td>&nbsp;</td><td valign="top"><a href="#Recipes">Recipes</a></td>
</tr>
<tr><td colspan="4">
<hr></td></tr>
<tr><th><a name="Index_cp_letter-V">V</a></th><td></td><td></td></tr>
<tr><td></td><td valign="top"><a href="#index-variables">variables</a>:</td><td>
&nbsp;</td><td valign="top"><a href="#Recipes">Recipes</a></td></tr>
<tr><td colspan="4">
<hr></td></tr>
<tr><th><a name="Index_cp_letter-W">W</a></th><td></td><td></td></tr>
<tr><td></td><td valign="top"><a href="#index-writing-recipes">writing
 recipes</a>:</td><td>&nbsp;</td><td valign="top"><a href="#Recipes">Recipes</a>
</td></tr>
<tr><td colspan="4">
<hr></td></tr>
</table>
<table>
<tr><th valign="top">Jump to: &nbsp;</th><td><a class="summary-letter" href="#Index_cp_letter-C">
<b>C</b></a> &nbsp; <a class="summary-letter" href="#Index_cp_letter-E"><b>E</b>
</a> &nbsp; <a class="summary-letter" href="#Index_cp_letter-H"><b>H</b></a>
 &nbsp; <a class="summary-letter" href="#Index_cp_letter-I"><b>I</b></a> &nbsp; <a class="summary-letter"
href="#Index_cp_letter-M"><b>M</b></a> &nbsp; <a class="summary-letter" href="#Index_cp_letter-P">
<b>P</b></a> &nbsp; <a class="summary-letter" href="#Index_cp_letter-R"><b>R</b>
</a> &nbsp; <a class="summary-letter" href="#Index_cp_letter-S"><b>S</b></a>
 &nbsp; <a class="summary-letter" href="#Index_cp_letter-T"><b>T</b></a> &nbsp; <a class="summary-letter"
href="#Index_cp_letter-V"><b>V</b></a> &nbsp; <a class="summary-letter" href="#Index_cp_letter-W">
<b>W</b></a> &nbsp;</td></tr>
</table>
<div class="footnote">
<hr>
<h3 class="footnotes-heading">Footnotes</h3>
<h3><a href="#DOCF1" name="FOOT1">(1)</a></h3>
<p>The official guide for Graft can be found at <a href="http://peters.gormand.com.au/Home/tools/graft/graft.html">
http://peters.gormand.com.au/Home/tools/graft/graft.html</a>.</p>
<h3><a href="#DOCF2" name="FOOT2">(2)</a></h3>
<p>The proposal for &lsquo;<samp>license</samp>&rsquo; was made by Richard M.
 Stallman at <a href="http://lists.gnu.org/archive/html/gnu-linux-libre/2016-05/msg00003.html">
http://lists.gnu.org/archive/html/gnu-linux-libre/2016-05/msg00003.html</a>
.</p>
</div>
<hr>
<center>
<h1><a NAME="6"><em>Graft</em> - a package management utility</a></h1>
</center>
<h2><a NAME="6_1">Prepared by Peter Samuel <a href="mailto:peter.r.samuel@gmail.com">
<tt>&lt;peter.r.samuel@gmail.com&gt;</tt></a></a></h2>
<h3>$Revision: 2.16 $</h3>
<h4>$Date: 2018/04/16 14:54:07 $</h4>
<blockquote>
<p><em><strong> graft:</strong> To insert (a graft) in a branch or stem
 of another tree; to propagate by insertion in another stock; also, to
 insert a graft upon. To implant a portion of (living flesh or skin) in
 a lesion so as to form an organic union. To join (one thing) to another
 as if by grafting, so as to bring about a close union.</em></p>
</blockquote>
<hr>
<h2><a name="contents">Contents</a></h2>
<ul>
<li> <a href="#intro">Introduction</a></li>
<li> <a href="#rationale">Rationale</a></li>
<li> <a href="#research">Research</a></li>
<li> <a href="#design">Design</a>
<ul>
<li> <a href="#precedence">Control file precedence &amp; conflict resolution</a>
</li>
</ul>
</li>
<li> <a href="#history">History</a></li>
<li> <a href="#installation">Installation</a>
<ul>
<li> <a href="#rpm_and_deb">Creating RPM and DEB packages</a></li>
<li> <a href="#gotchas">Grafting<em> Graft</em> and<em> Perl</em> - the
 bootstrap problem</a></li>
</ul>
</li>
<li> <a href="#using-graft">Using<em> Graft</em></a>
<ul>
<li> <a href="#compiling-packages">Compiling Packages</a></li>
<li><a href="#usage"><em>Graft</em> command line options</a>
<ol>
<li><a href="#graft-i">Install</a></li>
<li><a href="#graft-d">Delete</a></li>
<li><a href="#graft-p">Prune</a></li>
<li><a href="#graft-L">Information</a></li>
</ol>
</li>
<li> <a href="#testing">Testing the<em> Graft</em> Installation</a></li>
<li> <a href="#installing-packages">Installing Packages</a></li>
<li> <a href="#bypass">Bypassing package directories</a></li>
<li> <a href="#include">Including specific files and/or directories</a></li>
<li> <a href="#exclude">Excluding specific files and/or directories</a></li>
<li> <a href="#config_dirs">Grafting configuration files</a></li>
<li><a href="#partial-graft">Grafting part of a package</a></li>
<li> <a href="#deleting-packages">Deleting and/or Upgrading Packages</a></li>
<li><a href="#transitioning">Transitioning a package to<em> Graft</em>
 control</a></li>
<li> <a href="#conflicts">Conflict Processing</a></li>
<li> <a href="#exitstatus">Exit Status</a></li>
</ul>
</li>
<li> <a href="#other-pkg-tools">Using<em> Graft</em> with other package
 management tools</a></li>
<li> <a href="#availability">Availability</a></li>
<li> <a href="#license">License</a></li>
</ul>
<hr>
<h2><a name="intro">Introduction</a></h2>
<p><em> Graft</em> provides a mechanism for managing multiple packages
 under a single directory hierarchy. It was inspired by both<em> Depot</em>
 (Carnegie Mellon University) and<em> Stow</em> (Bob Glickstein).</p>
<p> For the purposes of this discussion a<em> package</em> is defined as
 a suite of programs and files that make up an individual product. For
 example, the<em> package</em> known as<em> gcc</em> consists of the
 compiler and preprocessor programs, include files, manual pages and any
 other associated file or program. The concept of a<em> package</em>
 should not be confused with some vendor's definitions that are - by
 this definition - actually collections of<em> packages</em>.</p>
<p> Special thanks to Gordon Rowell, Charles Butcher, Charlie Brady,
 Robert Maldon and Matias A. Fonzo for design suggestions and
 contributions.</p>
<hr>
<h2><a name="rationale">Rationale</a></h2>
<p> In any reasonably large environment, many software packages will be
 installed. The installation location for these packages usually follows
 one of three rationales - each with its own advantages and drawbacks:</p>
<ol>
<li>
<p> Each package is isolated from all other packages by installing it
 into a self contained directory tree. All binaries, manual pages,
 library and configuration files are stored under a single directory
 tree. This directory tree contains NO other files which are not the
 exclusive domain of the package in question.</p>
<p> This method makes package demarcation obvious. As each package is
 self contained, identification of any file within a package is
 immediately apparent.</p>
<p> Multiple versions of packages can be installed fairly easily to
 accommodate acceptance testing of new versions and/or legacy systems.</p>
<p> However, the use of individual package directories can lead to VERY
 long<strong> $PATH</strong> and<strong> $MANPATH</strong> environment
 variables. Some shells may not be able to handle such long variables.
 Whenever a new package is added, each user MUST update their<strong>
 $PATH</strong> and<strong> $MANPATH</strong> to make the package
 available.</p>
</li>
<li>
<p> Packages are installed under a common directory tree. Binaries for
 all packages are grouped in a single directory, manual pages for all
 packages in another directory and so on.</p>
<p> This method eliminates the need for continually updating long<strong>
 $PATH</strong> variables for each user. As soon as a package is placed
 into the common '<tt>bin</tt>' directory it is immediately available to
 all users (after a shell rehash if necessary).</p>
<p> However, when a package is to be updated it is often very difficult
 to isolate all the files related to a particular package if they are
 intermingled with unrelated files.</p>
</li>
<li>
<p> A combination of methods (1) and (2).</p>
</li>
</ol>
<p> In an effort to maximise the advantages and minimise the
 disadvantages,<em> Depot</em>,<em> Stow</em> and<em> Graft</em> adopt a
 similar philosophy:</p>
<blockquote>
<p> Packages are installed in self contained directory trees and
 symbolic links from a common area are made to the package files.</p>
</blockquote>
<p> This approach allows multiple versions of the same package to
 co-exist on the one system. One version is the commonly available
 version and symbolic links will be made to this version. New versions
 can be tested and once acceptable can replace the current commonly
 available version. Older versions can still be used for legacy systems
 by using the '<em>real</em>' path name to the package instead of the '<em>
common</em>' path name.</p>
<p> The size and complexity of environment variables such as<strong>
 $PATH</strong> and<strong> $MANPATH</strong> is minimised because only
 the common area is required. Any special cases can also be accommodated
 but these will usually be in the minority when compared with the number
 of commonly available packages.</p>
<hr>
<h2><a name="research">Research</a></h2>
<p><strong> Note:</strong> Development of<em> Graft</em> began in late
 1996. The comments regarding the packages listed below reflect their
 functionality and behaviour at that time and may not necessarily
 reflect their current functionality and behaviour.</p>
<p> As stated earlier,<em> Graft</em> was inspired by<em> Depot</em> and<em>
 Stow</em>. Both these systems were examined and finally rejected for
 the following reasons:</p>
<dl>
<dt><em> Depot</em> <a href="ftp://ftp.andrew.cmu.edu/pub/depot/depot.tar.gz">
ftp://ftp.andrew.cmu.edu/pub/depot/depot.tar.gz</a></dt>
<dd>
<p><em> Depot</em> is very flexible yet cumbersome.</p>
<p> It requires a database file to be created which provides a snapshot
 of the current state of both the package repository and the<em> Depot</em>
 target. It is possible to inadvertently destroy the package repository
 if the database is damaged.</p>
<p><em> Depot</em> assumes &quot;<em>ownership</em>&quot; of the target area,
 making it almost impossible to accommodate packages that are not under
 the control of<em> Depot</em>. (&quot;<em>Ownership</em>&quot; in this case means
 that<em> Depot</em> assumes ALL files in the target area will be under
 the control of<em> Depot</em>. It does not imply that<em> Depot</em>
 modifies Unix file permissions).</p>
<p> Because of<em> Depot</em>'s assumed<em> ownership</em> it is
 difficult for other packages not under the control of<em> Depot</em> to
 be placed in the same target area.</p>
<p><em> Depot</em> attempts to impose a fixed package repository
 relative to the package target. It assumes that all packages will be
 stored under '<tt><em>dir</em>/depot/<em>package</em></tt>' and the
 target will be '<tt><em>dir</em></tt>'. This can be overridden on the
 command line but the internals of<em> Depot</em> make this mechanism
 cumbersome.</p>
<p><em> Depot</em> is written in C and there are many source files in
 its distribution. Local modifications would be difficult to quickly
 implement and test.</p>
</dd>
<dt><em> Stow</em> <a href="https://www.gnu.org/software/stow/">
https://www.gnu.org/software/stow/</a></dt>
<dd>
<p><em> Stow</em> is a stateless system. It requires no database or
 configuration information.</p>
<p> Like<em> Depot</em>, it assumes that the package repository will be
 stored under '<tt><em>dir</em>/stow/<em>package</em></tt>' and the
 target will be '<tt><em>dir</em></tt>'. This can be overridden on the
 command line and works well during the install phase.</p>
<p><em> Stow</em> assumes &quot;<em>ownership</em>&quot; of the target area,
 making it difficult to accommodate packages that are not under the
 control of<em> Stow</em>. (&quot;<em>Ownership</em>&quot; in this case means that<em>
 Stow</em> assumes ALL files in the target area will be under the
 control of<em> Stow</em>. It does not imply that<em> Stow</em> modifies
 Unix file permissions).</p>
<p> Because of<em> Stow</em>'s assumed<em> ownership</em> it is
 difficult for other packages not under the control of<em> Stow</em> to
 be placed in the same target area. When deleting packages,<em> Stow</em>
 examines everything in the target directory - whether it is associated
 with the package it is trying to delete or not. This can be time
 consuming and potentially dangerous as empty directories are also
 removed - even empty directories that do not belong to the package
 being removed.</p>
<p><em> Stow</em> has a clever feature of<em> folding</em> and<em>
 unfolding</em> directories. It attempts to optimise the number of
 symbolic links by making links to directories if the directory is only
 associated with a single package. If at a later date<em> Stow</em>
 discovers another package that needs that directory it will<em> unfold</em>
 that directory into a collection of symbolic links to files rather than
 a single symbolic link to the directory.<em> Stow</em> will<em> fold</em>
 the directory when removing packages if the remainder of the directory
 is only concerned with a single package. While clever, this feature is
 probably a waste of time and effort. It means that the entire package
 target must be scanned to determine package ownership of links and as
 packages will usually be replaced by newer versions a directory<em>
 fold</em> will probably be short lived.</p>
<p><em> Stow</em> will sometimes miss potential conflicts when run in<em>
 show only</em> mode. The conflicts may occur when a directory is
 unfolded and will not show up in<em> show only</em> mode.</p>
<p><em> Stow</em>'s author suggests that packages be compiled such that
 they refer to files in the target location rather than the actual
 package installation directory. This approach precludes the use of
 multiple versions of packages with different configuration and/or
 library files.</p>
<p><em> Stow</em> is written in<em> Perl</em> and is only a few hundred
 lines of code so local modifications can be accommodated. However there
 are very few comments in the code which makes the process of
 modification difficult.</p>
</dd>
</dl>
<p> Since the release of<em> Graft</em> 1.6, the existence of yet
 another packaging program has been brought to the author's attention.</p>
<dl>
<dt><em> Encap</em> <a href="http://www.ks.uiuc.edu/Development/Computers/docs/sysadmin/Build/encap.html">
http://www.ks.uiuc.edu/Development/Computers/docs/sysadmin/Build/encap.html
</a></dt>
<dd>
<p><em> Encap</em> grew out of work begun at the University of Illinois
 Champaign-Urbana. It has the same underlying philosophy as<em> Depot</em>
,<em> Stow</em> and<em> Graft</em> - encapsulate packages into self
 contained directories and use symbolic links to make them visible in a
 common location.</p>
<p><em> Encap</em> uses a combination of a<em> csh</em> wrapper and a<em>
 Perl</em> program to accomplish its work. Like both<em> Depot</em> and<em>
 Stow</em>,<em> Encap</em> assumes that all compiled packages will live
 under a single directory hierarchy - by default '<tt><em>dir</em>
/encap/<em>package</em></tt>'. It then attempts to create a symbolic
 link tree for ALL the packages under this area. There doesn't appear to
 be any easy way to support the quick addition or removal of a single
 package.</p>
<p> A new release of<em> Encap</em> incorporating many new features was
 expected to be available in early 1997, however no release greater than
 version 1.2 has been forthcoming.</p>
<p> One good feature of<em> Encap</em> is the ability to exclude
 specific files from the package tree. This concept has been
 incorporated into<em> Graft</em> 1.7 and above.</p>
</dd>
</dl>
<p> Since the release of<em> Graft</em> 2.3, the existence of several
 another packaging programs have been brought to the author's attention.
 Rather than outline their features and whether or not the author feels
 they are superior (or inferior) to<em> Graft</em>, a reference to each
 package and a brief description is given and further research is left
 as an exercise for the reader:</p>
<dl>
<dt><em> stowES</em></dt>
<dd>
<pre>
<a href="https://os.inf.tu-dresden.de/~adam/stowES/">https://os.inf.tu-dresden.de/~adam/stowES/</a>
</pre>
<p> &quot;<em>stowES (stow Enhancement Script) is a Perl script which tries
 to ease the use of the &quot;stow&quot; packaging program and software which can
 be compiled and installed with autoconf. It automates the compilation
 and installation of software packages and provides some useful
 functions to maintain your stow packages (e.g., list packages, check
 packages for integrity, etc.).</em>&quot;</p>
</dd>
<dt><em> opt_depot</em></dt>
<dd>
<pre>
<a href="https://github.com/jonabbey/opt_depot">https://github.com/jonabbey/opt_depot</a>
</pre>
<p> &quot;<em>opt_depot is a suite of Perl scripts which makes it easy to
 manage installed software across a wide range of client systems.
 opt_depot makes it possible to keep all files associated with a program
 together in one directory, so installation and de-installation is
 simple. opt_depot is easy to manage, and provides a scheme for
 installing software in a truly portable fashion; packages may be
 installed locally on client systems, or kept in a central package
 archive for NFS access.</em> &quot;</p>
<p> This site also has links to several other package management
 utilities, including<em> Graft</em>.</p>
</dd>
<dt><em> relink</em></dt>
<dd>
<pre>
<a href="http://sourceforge.net/projects/relink/">http://sourceforge.net/projects/relink/</a>
</pre>
<p> &quot;<em>relink is a package management tool for organization and
 management of software packages. It should run on any UNIX platform
 that runs PERL. Similar tools include: rpm(REDHAT/Mandrake),
 pkgadd(Slackware/SUN), stow(GNU) and depot(CMU)</em>&quot;</p>
</dd>
<dt><em> univSrcPkg</em></dt>
<dd>
<pre>
<a href="http://freecode.com/articles/the-universal-source-package">http://freecode.com/articles/the-universal-source-package</a>
</pre>
<p> <a href="mailto:bud@sistema.it">Bud Bruegger</a> has written a brief
 paper outlining his thoughts on a &quot;<em>Universal Source Package</em>&quot;
 solution.</p>
<p> This site also has links to other package management programs and
 similar items of interest.</p>
</dd>
</dl>
<hr>
<h2><a name="design">Design</a></h2>
<p> This brings us to<em> Graft</em>.<em> Graft</em> has been designed
 to use the best features of<em> Depot</em>,<em> Stow</em> and<em> Encap</em>
 while maintaining as simple a mechanism as possible. The principles of<em>
 Graft</em> are:</p>
<ul>
<li>
<p><em> Graft</em> will allow packages to be<em> grafted</em> from any
 directory to any other directory. Default <tt>installation</tt> and <tt>
target</tt> directories will be used but can easily be overridden on the
 command line.</p>
</li>
<li>
<p><em> Graft</em> will log its actions to a log file. The log file can
 be specified on the command line. If not specified on the command line
 a default log file will be used.</p>
</li>
<li>
<p><em> Graft</em> will NOT create symbolic links to directories. If a
 directory does not exist in the target tree it will be created (with
 the same ownership and permissions as the original if desired).</p>
</li>
<li>
<p><em> Graft</em> will create symbolic links with full pathnames rather
 than relative pathnames. This allows easy identification of true
 package locations and facilitates block movement of a target tree
 without the need for<em> Graft</em> deletion and re-installation.</p>
</li>
<li>
<p><em> Graft</em> will cease installation of a package if a conflict
 arises. A conflict is defined as one of the following conditions:</p>
<ul>
<li> If the package object is a directory and the target object exists
 but is not a directory.</li>
<li> If the package object is not a directory and the target object
 exists and is not a symbolic link.</li>
<li> If the package object is not a directory and the target object
 exists and is a symbolic link to something other than the package
 object.</li>
<li> If the package directory contains a <tt>.graft-config</tt> file and
 the target object exists but does not match the 32-bit CRC of the
 package object.</li>
</ul>
</li>
<li>
<p> Installation conflicts will always be reported. Conflicts will be
 reported to standard error.</p>
</li>
<li>
<p><em> Graft</em> will attempt to display all possible operations when
 asked, even when asked not to perform the operations.</p>
</li>
<li>
<p><em> Graft</em> will not delete directories when uninstalling.<em>
 Graft</em> will print an appropriate message if an empty directory
 results and leave the deletion for the operator to perform outside the
 scope of<em> Graft</em>'s operations. This ensures that<em> place
 holder</em> directories that may be used by other packages are not
 inadvertently removed. This feature can be permanently disabled by
 setting a flag in the <tt>Makefile</tt>. It can also be temporarily
 disabled using a command line option.</p>
</li>
<li>
<p><em> Graft</em> will continue to delete the remainder of a package
 after a conflict arises. This maximises the amount of deletion that can
 be performed.</p>
</li>
<li>
<p> Deletion conflicts will always be reported. Conflicts will be
 reported to standard error.</p>
</li>
<li>
<p><em> Graft</em> will only concern itself with files relating to the
 package at hand. This will allow other packages to be placed in the
 target area without fear of intervention by<em> Graft</em>.</p>
</li>
<li>
<p><em> Graft</em> will only allow the superuser to install or delete
 packages. This feature can be permanently disabled by setting a flag in
 the <tt>Makefile</tt> or it may be overridden by a command line option.</p>
</li>
<li>
<p> If the file <tt>.nograft</tt> exists in any package directory,<em>
 Graft</em> will bypass that directory and any subdirectories during
 installation. The name of this file is specified in the <tt>Makefile</tt>
.</p>
</li>
<li>
<p> When installing a directory tree, if the file <tt>.graft-exclude</tt>
 exists in any package directory,<em> Graft</em> will assume that the
 file contains a list of file and/or directory names - one per line -
 which correspond to files and/or directories in the directory
 containing the <tt>.graft-exclude</tt> file. These files and/or
 directories will NOT be<em> grafted</em>. The name of this file is
 specified in the <tt>Makefile</tt>.</p>
<p> The <tt>.nograft</tt> file takes priority over the <tt>
.graft-exclude</tt> file.</p>
</li>
<li>
<p> When installing a directory tree, if the file <tt>.graft-include</tt>
 exists in any package directory,<em> Graft</em> will assume that the
 file contains a list of file and/or directory names - one per line -
 which correspond to files and/or directories in the directory
 containing the <tt>.graft-include</tt> file. ONLY the files and/or
 directories listed in the <tt>.graft-include</tt> will be<em> grafted</em>
. The name of this file is specified in the <tt>Makefile</tt>.</p>
<p> The <tt>.graft-exclude</tt> file takes priority over the <tt>
.graft-include</tt> file.</p>
</li>
<li>
<p> When installing a directory tree, if the file <tt>.graft-config</tt>
 exists in a package directory, the contents of the directory will be<strong>
 copied</strong> to the target directory. If the target files exists and
 is in conflict with the package file then the package file will be
 copied into the target directory as <tt>file<em>.new</em></tt>.</p>
<p> The <tt>.graft-include</tt> file takes priority over the <tt>
.graft-config</tt> file.</p>
</li>
<li>
<p> If the file <tt>.nograft</tt> exists in any package directory, it
 will be ignored and<em> Graft</em> will continue processing the
 directory and any subdirectories during deletion.</p>
</li>
<li>
<p> If the file <tt>.graft-exclude</tt> exists in any package directory,
 its contents will be ignored and<em> Graft</em> will continue
 processing the directory and any subdirectories during deletion.</p>
</li>
<li>
<p> If the file <tt>.graft-include</tt> exists in any package directory,
 its contents will be ignored and<em> Graft</em> will continue
 processing the directory and any subdirectories during deletion.</p>
</li>
<li>
<p> If the file <tt>.graft-config</tt> exists in any package directory,
 during deletion matching files in the target directory will not be
 deleted however any <tt>file<em>.new</em></tt> files will be deleted.</p>
</li>
<li>
<p> As an aid to transitioning systems to<em> Graft</em>,<em> Graft</em>
 will allow conflicting files to be pruned. This pruning can take the
 form of a file rename or a file removal depending on either a <tt>
Makefile</tt> flag or a command line option. If file removal is selected
 and the file is a non-empty directory, it will be renamed instead.</p>
</li>
<li>
<p> If the file <tt>.nograft</tt> exists in any package directory, it
 will be ignored and<em> Graft</em> will continue processing the
 directory and any subdirectories during pruning.</p>
</li>
<li>
<p> If the file <tt>.graft-exclude</tt> exists in any package directory,
 its contents will be ignored and<em> Graft</em> will continue
 processing the directory and any subdirectories during pruning.</p>
</li>
<li>
<p> If the file <tt>.graft-include</tt> exists in any package directory,
 its contents will be ignored and<em> Graft</em> will continue
 processing the directory and any subdirectories during pruning.</p>
</li>
<li>
<p> If the file <tt>.graft-config</tt> exists in any package directory,
 the files in the directory will be ignored during pruning.
 Sub-directories will continue to be processed appropriately.</p>
</li>
</ul>
<h3><a name="precedence">Control file precedence &amp; conflict resolution</a>
</h3>
<p> As stated above, the various<em> Graft</em> control files have the
 following precedence, from highest to lowest:</p>
<pre>
    .nograft &gt; .graft-exclude &gt; .graft-include &gt; .graft-config
</pre>
<p> The following table summarises the activities of<em> Graft</em> when
 various control files are present:</p>
<center>
<table border="2" cellpadding="3" summary="Control File Precedence">
<tr><th colspan="5"> Install</th></tr>
<tr><th><em> Target</em></th><th><em> .nograft</em></th><th><em>
 .graft-exclude</em></th><th><em> .graft-include</em></th><th><em>
 .graft-config</em></th></tr>
<tr><td> does not exist</td><td> IGNORE</td><td> IGNORE</td><td> SYMLINK</td><td>
 COPY</td></tr>
<tr><td> symlink to source</td><td> IGNORE</td><td> IGNORE</td><td> NOP</td><td>
 DELETE &amp; COPY</td></tr>
<tr><td> symlink to other</td><td> IGNORE</td><td> IGNORE</td><td>
 CONFLICT</td><td> N/A</td></tr>
<tr><td> symlink to other (crc match)</td><td> N/A</td><td> N/A</td><td>
 N/A</td><td> NOP</td></tr>
<tr><td> symlink to other (crc diff)</td><td> N/A</td><td> N/A</td><td>
 N/A</td><td> COPY.new</td></tr>
<tr><td> file</td><td> IGNORE</td><td> IGNORE</td><td> CONFLICT</td><td>
 N/A</td></tr>
<tr><td> file (crc match)</td><td> N/A</td><td> N/A</td><td> N/A</td><td>
 NOP</td></tr>
<tr><td> file (crc diff)</td><td> N/A</td><td> N/A</td><td> N/A</td><td>
 COPY.new</td></tr>
<tr><td> not a file</td><td> IGNORE</td><td> IGNORE</td><td> CONFLICT</td><td>
 CONFLICT</td></tr>
<tr><th colspan="5"> Delete</th></tr>
<tr><th><em> Target</em></th><th><em> .nograft</em></th><th><em>
 .graft-exclude</em></th><th><em> .graft-include</em></th><th><em>
 .graft-config</em></th></tr>
<tr><td> does not exist</td><td> NOP</td><td> NOP</td><td> NOP</td><td>
 NOP</td></tr>
<tr><td> symlink to source</td><td> DELETE</td><td> DELETE</td><td>
 DELETE</td><td> DELETE &amp; DELETE.new</td></tr>
<tr><td> symlink to other</td><td> CONFLICT</td><td> CONFLICT</td><td>
 CONFLICT</td><td> N/A</td></tr>
<tr><td> symlink to other (crc match)</td><td> N/A</td><td> N/A</td><td>
 N/A</td><td> DELETE.new</td></tr>
<tr><td> symlink to other (crc diff)</td><td> N/A</td><td> N/A</td><td>
 N/A</td><td> NOP</td></tr>
<tr><td> file</td><td> NOTE</td><td> NOTE</td><td> CONFLICT</td><td> N/A</td>
</tr>
<tr><td> file (crc match)</td><td> N/A</td><td> N/A</td><td> N/A</td><td>
 DELETE.new</td></tr>
<tr><td> file (crc diff)</td><td> N/A</td><td> N/A</td><td> N/A</td><td>
 NOP</td></tr>
<tr><td> not a file</td><td> CONFLICT</td><td> CONFLICT</td><td>
 CONFLICT</td><td> CONFLICT</td></tr>
<tr><th colspan="5"> Prune</th></tr>
<tr><th><em> Target</em></th><th><em> .nograft</em></th><th><em>
 .graft-exclude</em></th><th><em> .graft-include</em></th><th><em>
 .graft-config</em></th></tr>
<tr><td> does not exist</td><td> NOP</td><td> NOP</td><td> NOP</td><td>
 N/A</td></tr>
<tr><td> symlink to source</td><td> NOP</td><td> NOP</td><td> NOP</td><td>
 N/A</td></tr>
<tr><td> symlink to other</td><td> PRUNE</td><td> PRUNE</td><td> PRUNE</td><td>
 N/A</td></tr>
<tr><td> file</td><td> PRUNE</td><td> PRUNE</td><td> PRUNE</td><td> N/A</td>
</tr>
<tr><td> not a file</td><td> PRUNE</td><td> PRUNE</td><td> PRUNE</td><td>
 N/A</td></tr>
</table>
</center>
<hr>
<h2><a name="history">History</a></h2>
<p> Development on<em> Graft</em> began in October 1996. The initial
 design used a configuration file to map the installed location of each
 package to its target directory (that is the directory in which the
 symbolic links would be created). Work proceeded at a regular pace and
 by November 1997<em> Graft</em> version<em> 2.1</em> was released. In
 this, and all subsequent versions, the configuration file had been
 removed in favour of using default source and target directories.</p>
<p> No further work was performed until September 2000 when the concept
 of bypassing or including files and directories using <tt>.nograft</tt>
 or <tt>.graft-include</tt> files was introduced in<em> Graft</em>
 version<em> 2.3</em>.</p>
<p> Again nothing changed until February 2002 when Rod Whitby identified
 a bug in the handling of <tt>.graft-include</tt> files. Several other
 users (Peter Bray, Robert Maldon and others) also reported some
 deprecation warnings when using<em> Graft</em> with<em> Perl</em>
 version<em> 5.6.0</em>.<em> Graft</em> version<em> 2.4</em> was the end
 of<em> Graft</em> development for over a decade.</p>
<p> In May 2015 Matias A. Fonzo contacted the author wishing to use<em>
 Graft</em> in the <a href="http://www.dragora.org/">Dragora GNU/Linux</a>
 distribution. Matias' usage of<em> Graft</em> lead to<em> Graft</em>
 version<em> 2.5</em> in June 2015 whereby the <tt>-P</tt> command line
 option was silently ignored if the effective user was not root.</p>
<p> Since the release of<em> Graft</em> version<em> 2.4</em> the
 author's<em> Perl</em> code had improved somewhat so<em> Graft</em>
 version<em> 2.6</em> released in July 2015 represented a major clean up
 of coding style and internals. No new behaviours or features were added
 to the<em> 2.6</em> release.</p>
<p> Matias made some more suggestions and improvements up to and
 including<em> Graft</em> version<em> 2.16</em> in April 2018. These
 changes added the <tt>.graft-config</tt> control file, the <tt>-r
 /rootdir</tt> option for specifying a new root directory, the <tt>-L</tt>
 option for displaying default locations as well as introducing some
 tighter controls on the messages and exit status of<em> Graft</em>
 under various conditions.</p>
<hr>
<h2><a name="installation">Installation</a></h2>
<p> Before installing<em> Graft</em> you'll need<em> Perl</em> 5.<em>x</em>
.<em> Graft</em> version 2.<em>x</em> requires features only available
 with<em> Perl</em> 5.<em>x</em> and will not run with<em> Perl</em> 4.<em>
x</em>.</p>
<p> Your operating system and its file system(s) should also support
 symbolic links. If you can't make symbolic links then you can't use<em>
 Graft</em>!<em> Graft</em> will exit gracefully if your version of<em>
 Perl</em> does not support symbolic links. It will also exit gracefully
 if you attempt to<em> graft</em> a package into a file system that does
 not support symbolic links - from a Linux <tt>ext4</tt> file system
 into an <tt>vfat</tt> file system for example.</p>
<p><em> Graft</em> has been written to ensure it uses<em> Perl</em>
 modules that are considered part of the core<em> Perl</em>
 distribution. However it may be possible that you're using a home grown
 installation of<em> Perl</em> or some distribution that doesn't have
 the same<em> Perl</em> modules as the author's development environment.</p>
<p> If this is the case you'll see compile failures for the following
 modules if they are unavailable:</p>
<pre>
   File::Basename
   Getopt::Long
</pre>
<p> You will not be able to install<em> Graft</em> until these modules
 are available.</p>
<p> You may also see run-time failures when using<em> Graft</em> with <tt>
.graft-config</tt> files if the following modules are unavailable:</p>
<pre>
   Compress::Raw::Zlib    (<em>used in install and delete modes</em>)
   File::Copy             (<em>only used in install mode</em>)
</pre>
<p> If you don't have these modules and you do not intend to use <tt>
.graft-config</tt> files then you can continue to use<em> Graft</em>
 without issue.</p>
<p> Follow these instructions to install<em> Graft</em>:</p>
<ol>
<li>
<p> Unpack the gzipped<em> Graft</em> distribution:</p>
<pre>
    gunzip -c graft-2.16.tar.gz | tar xvf -
</pre>
</li>
<li>
<p> change directories to the<em> Graft</em> distribution directory:</p>
<pre>
    cd graft-2.16
</pre>
</li>
<li>
<p> Create an writable version of the <tt>Makefile</tt> by running the
 command</p>
<pre>
    make -f Makefile.dist
</pre>
<p> You'll see output similar to</p>
<pre>
    cp Makefile.dist Makefile
    chmod 644 Makefile

    ######################################################
    #                                                    #
    #       You'll now need to modify the Makefile       #
    #      variables to suit your local conditions.      #
    #                                                    #
    ######################################################

    make: *** [Makefile] Error 1
</pre>
<p> You can ignore the error message. That is just there to prevent the
 creation of the<em> graft</em> executable before you've made your site
 specific configurations to the <tt>Makefile</tt>.</p>
</li>
<li>
<p> Edit the <tt>Makefile</tt>. The following variables should be
 modified to suit your local requirements:</p>
<dl>
<dt>
<pre>
<strong>PACKAGEDIR</strong>     = /usr/local/pkgs
<strong>TARGETDIR</strong>      = /usr/local
</pre>
</dt>
<dd>
<p> These two variables control your default package <tt>installation</tt>
 and <tt>target</tt> directories. Most sites will probably choose to
 install packages under a common <tt>installation</tt> directory and
 then<em> graft</em> them into a common <tt>target</tt> directory.</p>
<p> If no specific <tt>target</tt> directory is given on the command
 line,<em> Graft</em> will use the default value specified by<strong>
 TARGETDIR</strong>. If a <tt>target</tt> directory is given on the
 command line but is not fully qualified, the value specified by<strong>
 TARGETDIR</strong> will be prepended to the command line argument.</p>
<p> Package names provided to<em> Graft</em> that are not fully
 qualified will have the value specified by<strong> PACKAGEDIR</strong>
 prepended to the command line arguments.</p>
</dd>
<dt>
<pre>
<strong>TOP</strong>            = $(PACKAGEDIR)/graft-$(VERSION)
<strong>BIN</strong>            = $(TOP)/bin
<strong>MAN</strong>            = $(TOP)/man
<strong>DOC</strong>            = $(TOP)/doc
</pre>
</dt>
<dd>
<p> There should be no need to modify these values unless you wish to
 install<em> Graft</em> into a directory that is different from your
 default package installation directory. If you do modify<strong> TOP</strong>
 you should not change the values of<strong> BIN</strong>,<strong> MAN</strong>
 and<strong> DOC</strong>. If you feel you must change these values then
 perhaps you've misunderstood the concept behind<em> Graft</em> so a
 re-read of this document may be in order.</p>
</dd>
<dt>
<pre>
<strong>PERL</strong>           = /usr/bin/perl
</pre>
</dt>
<dd>
<p> This variable refers to the location of the<em> Perl</em> 5.<em>x</em>
 that will be used by the<em> Graft</em> executable. If you plan on<em>
 grafting</em><em> Perl</em> then this value should be the<em> grafted</em>
 location of<em> Perl</em> rather than the installation location of<em>
 Perl</em>. If you are using an operating system that comes with<em>
 Perl</em> 5.<em>x</em> - such as RedHat or Ubuntu Linux - then you
 don't need to worry about<em> grafting</em><em> Perl</em> so the value
 of<strong> PERL</strong> should reflect its installed location.</p>
<p> Most Unix, Linux and other Unix like operating systems ship with<em>
 Perl</em> these days so modifying this value is probably unnecessary.</p>
</dd>
<dt>
<pre>
<strong>BUILDPERL</strong>      = $(PERL)
</pre>
</dt>
<dd>
<p><em> Perl</em> is required during the <tt>make</tt>. You'll only need
 to change this if the current installed location of<em> Perl</em> is
 different to the future<em> grafted</em> location of<em> Perl</em>.</p>
</dd>
<dt>
<pre>
<strong>LOGFILE</strong>                = /var/log/graft
</pre>
</dt>
<dd>
<p><em> Graft</em> logs all of its actions to a log file. Modify the
 value of<strong> LOGFILE</strong> to suit your local needs. An
 alternative name can be specified on the command line.</p>
<p> If you want logging disabled by default, set the value of<strong>
 LOGFILE</strong> to <tt>/dev/null</tt>.</p>
</dd>
<dt>
<pre>
<strong>GRAFT-IGNORE</strong>   = .nograft
<strong>GRAFT-EXCLUDE</strong>  = .graft-exclude
<strong>GRAFT-INCLUDE</strong>  = .graft-include
<strong>GRAFT-CONFIG</strong>   = .graft-config
</pre>
</dt>
<dd>
<p> These variables hold the names of the special<em> Graft</em> files
 that control whether or not subdirectories or files are<em> grafted</em>
. If you change these values, try to choose obvious names. If you want
 the files to appear in a simple directory listing, do not use file
 names that begin with a dot &quot;.&quot; character.</p>
</dd>
<dt>
<pre>
<strong>GRAFT-NEVER</strong>    =
</pre>
</dt>
<dd>
<p> This variable holds the names of the files and/or directories that
 should never be<em> grafted</em>. Typically these may be source code
 repositories as used by systems such as<em> CVS</em>, or perhaps
 lockfiles. The default value is empty but if you wish to specify
 values, simply add them to the variable using only whitespace as a
 separator. For example:</p>
<pre>
GRAFT-NEVER     = CVS RCS SCCS .lock
</pre>
</dd>
<dt>
<pre>
<strong>NEVERGRAFT</strong>     = 0
</pre>
</dt>
<dd>
<p> If this variable is set to<strong> 1</strong>, the files and/or
 directories specified by<strong> GRAFT-NEVER</strong> will be
 automatically excluded from the<em> grafted</em> directory.</p>
<p> If this variable is set to<strong> 0</strong>, the files and/or
 directories specified by<strong> GRAFT-NEVER</strong> will be not be
 excluded from the<em> grafted</em> directory.</p>
<p> The sense of this value is reversed by use of the<strong> -C</strong>
 command line option.</p>
<p> The automatic exclusion is bypassed completely if the<em> grafted</em>
 directory contains either a <tt>.nograft</tt> or <tt>.graft-include</tt>
 file.</p>
</dd>
<dt>
<pre>
<strong>PRUNED-SUFFIX</strong>  = .pruned
</pre>
</dt>
<dd>
<p> This variable sets the suffix name of<em> pruned</em> files.<em>
 Pruned</em> files will be renamed<em> filename</em><tt>.pruned</tt>.</p>
</dd>
<dt>
<pre>
<strong>CONFIG-SUFFIX</strong>  = .new
</pre>
</dt>
<dd>
<p> This variable sets the suffix name of configuration files that will
 be copied to the target directory when the target object is in conflict
 with the package object. The files will be copied as<em> filename</em><tt>
.new</tt>.</p>
</dd>
<dt>
<pre>
<strong>SUPERUSER</strong>      = 1
</pre>
</dt>
<dd>
<p> If this variable is set to<strong> 1</strong> only the superuser can<em>
 install</em>,<em> delete</em> or<em> prune</em> packages. This can be
 overridden by the use of the<strong> -u</strong> command line option.
 If this variable is set to<strong> 0</strong>, superuser privileges are
 not required and the<strong> -u</strong> override command line option
 is disabled.</p>
<p> If you are installing a private copy of<em> Graft</em> to manage
 packages in your home directory you should set<strong> SUPERUSER</strong>
 to<strong> 0</strong>.</p>
<p> If you're using<em> Graft</em> to manage a global set of packages
 you should set<strong> SUPERUSER</strong> to<strong> 1</strong>.</p>
</dd>
<dt>
<pre>
<strong>PRESERVEPERMS</strong>  = 0
</pre>
</dt>
<dd>
<p> When<em> grafting</em> packages,<em> Graft</em> will create new
 directories as required. By setting<strong> PRESERVEPERMS</strong> to<strong>
 1</strong>, the original user id, group id and file modes will be
 carried over to the new directory. This variable is used only if<strong>
 SUPERUSER</strong> is set to<strong> 1</strong>. The sense of this
 variable can be reversed using the<strong> -P</strong> command line
 option.</p>
</dd>
<dt>
<pre>
<strong>DELETEOBJECTS</strong>  = 0
</pre>
</dt>
<dd>
<p> When deleting<em> grafted</em> packages,<em> Graft</em> may leave
 empty directories. Setting<strong> DELETEOBJECTS</strong> to<strong> 1</strong>
 will allow<em> Graft</em> to delete these directories. If<strong>
 DELETEOBJECTS</strong> is<strong> 0</strong> then<em> Graft</em> will
 display an appropriate message reminding the user that a directory has
 been emptied. The sense of this variable can be reversed using the<strong>
 -D</strong> command line option.</p>
<p> It's probably not good practise to set this value to<strong> 1</strong>
 as some directories may be used as place holders by a number of
 different packages. If the value is set to<strong> 0</strong> deletion
 of directories can be forced via the<strong> -D</strong> command line
 option.</p>
<p> When pruning packages,<em> graft</em> can either remove conflicting
 files or rename them. If<strong> DELETEOBJECTS</strong> is set to<strong>
 1</strong> the default prune action will be to delete conflicting
 objects. If<strong> DELETEOBJECTS</strong> is set to<strong> 0</strong>
 the default prune action will be to rename conflicting objects. The
 sense of this variable can be reversed using the<strong> -D</strong>
 command line option.</p>
</dd>
</dl>
<p> Save your changes and exit from the editor.</p>
</li>
<li>
<p> Remove any existing executables by running:</p>
<pre>
    make clean
</pre>
<p> You should see output similar to:</p>
<pre>
    rm -f graft
</pre>
</li>
<li>
<p> Create the<em> Graft</em> executable by running:</p>
<pre>
    make
</pre>
<p> You should see output similar to:</p>
<pre>
    /usr/bin/perl -wc graft.pl
    graft.pl syntax OK
    sed                                         \
        -e 's#xCONFIG-SUFFIXx#.new#g'           \
        -e 's#xDELETEOBJECTSx#0#g'              \
        -e 's#xGRAFT-CONFIGx#.graft-config#g'   \
        -e 's#xGRAFT-EXCLUDEx#.graft-exclude#g' \
        -e 's#xGRAFT-IGNOREx#.nograft#g'        \
        -e 's#xGRAFT-INCLUDEx#.graft-include#g' \
        -e 's#xGRAFT-NEVERx##g'                 \
        -e 's#xLOGFILEx#/var/log/graft#g'       \
        -e 's#xNEVERGRAFTx#0#g'                 \
        -e 's#xPACKAGEDIRx#/usr/local/pkgs#g'   \
        -e 's#xPERLx#/usr/bin/perl#g'           \
        -e 's#xPRESERVEPERMSx#0#g'              \
        -e 's#xPRUNED-SUFFIXx#.pruned#g'        \
        -e 's#xSUPERUSERx#1#g'                  \
        -e 's#xTARGETDIRx#/usr/local#g'         \
        &lt; graft.pl &gt; graft
    chmod +x graft
    /usr/bin/perl -wc graft
    graft syntax OK
    if [ -n &quot;&quot; ];                                       \
    then                                                \
        AUTOIGNORE=1;                                   \
    else                                                \
        AUTOIGNORE=0;                                   \
    fi;                                                 \
    sed                                                 \
        -e &quot;s#xAUTOIGNOREx#$AUTOIGNORE#g&quot;               \
        -e 's#xCONFIG-SUFFIXx#.new#g'                   \
        -e 's#xDELETEOBJECTSx#0#g'                      \
        -e 's#xDOCx#/usr/local/pkgs/graft-2.16/doc#g'   \
        -e 's#xGRAFT-CONFIGx#.graft-config#g'           \
        -e 's#xGRAFT-EXCLUDEx#.graft-exclude#g'         \
        -e 's#xGRAFT-IGNOREx#.nograft#g'                \
        -e 's#xGRAFT-INCLUDEx#.graft-include#g'         \
        -e 's#xGRAFT-NEVERx##g'                         \
        -e 's#xLOGFILEx#/var/log/graft#g'               \
        -e 's#xNEVERGRAFTx#0#g'                         \
        -e 's#xPACKAGEDIRx#/usr/local/pkgs#g'           \
        -e 's#xPERLx#/usr/bin/perl#g'                   \
        -e 's#xPRESERVEPERMSx#0#g'                      \
        -e 's#xPRUNED-SUFFIXx#.pruned#g'                \
        -e 's#xSUPERUSERx#1#g'                          \
        -e 's#xTARGETDIRx#/usr/local#g'                 \
        -e 's#xVERSIONx#2.16#g'                         \
        &lt; graft.man &gt; graft.1
</pre>
</li>
<li>
<p> If you're using the<em> automounter</em> under Solaris 2.<em>x</em>,
 the installation process may not be able to directly create the
 directory specified by<strong> TOP</strong>. If this is the case then
 manually create this directory using whatever procedures are
 appropriate for your operating system.</p>
<p> For example, if the <tt>/usr/local</tt> mount point is under the
 control of the<em> automounter</em> via an entry in the <tt>auto_pkgs</tt>
 map:</p>
<pre>
    *   nfshost:/export/sparc-SunOS-5.5.1/usr/local/&amp;
</pre>
<p> you'll need to create the<em> Graft</em> installation directory by
 executing the following command on the machine<em> nfshost</em>:</p>
<pre>
    mkdir /export/sparc-SunOS-5.5.1/usr/local/pkgs/graft-2.16
</pre>
</li>
<li>
<p> Install the<em> Graft</em> executable, manual page and documentation
 by executing:</p>
<pre>
    make install
</pre>
<p> You should see output similar to:</p>
<pre>
    mkdir -p /usr/local/pkgs/graft-2.16/bin
    cp graft /usr/local/pkgs/graft-2.16/bin

    for i in graft.1;                                              \
    do                                                             \
        manpage=`basename $i`;                                     \
        man=`expr $i : '.*\.\(.\)'`;                               \
        mkdir -p /usr/local/pkgs/graft-2.16/man/man$man;           \
        cp $i /usr/local/pkgs/graft-2.16/man/man$man/$manpage;     \
        chmod 644 /usr/local/pkgs/graft-2.16/man/man$man/$manpage; \
    done

    for i in graft.html graft.pdf graft.ps graft.txt;              \
    do                                                             \
        mkdir -p /usr/local/pkgs/graft-2.16/doc;                   \
        cp doc/$i /usr/local/pkgs/graft-2.16/doc;                  \
        chmod 644 /usr/local/pkgs/graft-2.16/doc/$i;               \
        touch /usr/local/pkgs/graft-2.16/doc/.nograft;             \
    done
</pre>
</li>
</ol>
<p><em> Graft</em> is now installed and ready to be used.</p>
<p><strong> NOTE:</strong> If you make changes to your<em> Graft</em>
 installation at a later date, please run the following commands:</p>
<pre>
    make clean
    make install
</pre>
<p> Failure to do this may result in a<em> Graft</em> manual page that
 does NOT reflect your current configuration.</p>
<h3><a name="rpm_and_deb">Creating RPM and DEB packages</a></h3>
<p> Beginning with<em> Graft</em> 2.11 there is now the ability to
 create RPM and Debian installation packages. Obviously you'll need one
 or more of the<em> rpmbuild</em> and<em> dpkg-deb</em> packages
 installed on your system.</p>
<p> After editing the <tt>Makefile</tt> to suit your environment simply
 run the appropriate <tt>make</tt> command to create the binary
 installation package in the current directory:</p>
<pre>
    make rpm
</pre>
<p> or</p>
<pre>
    make deb
</pre>
<p> The creation of these packages is somewhat experimental. Please let
 the author know if you have issues.</p>
<hr>
<h3><a name="gotchas">Grafting<em> Graft</em> and<em> Perl</em> - the
 bootstrap problem</a></h3>
<p><strong> If you are using an operating system that comes with<em>
 Perl</em> 5.<em>x</em> - such as RedHat or Ubuntu Linux - then you
 don't need to worry about<em> grafting</em><em> Perl</em>, so this
 section can be ignored.</strong></p>
<p><strong> However if you are a creator of an operating system
 distribution then this section may be relevant.</strong></p>
<p> Embedded into the<em> Graft</em> executable is the location of the<em>
 Perl</em> executable. If you've understood the concept behind<em> Graft</em>
 then this location may be the<em> grafted</em> location of<em> Perl</em>
 rather than the true location of<em> Perl</em>.</p>
<p> This presents a dilemma when you come to<em> graft</em> both<em>
 Graft</em> and<em> Perl</em>. You can't run the<em> grafted</em>
 location of the<em> Graft</em> executable because it doesn't exist yet,
 and you can't run the real location of the<em> Graft</em> executable
 because<em> Perl</em> hasn't been<em> grafted</em> yet.</p>
<p> Assuming that<em> Graft</em> and<em> Perl</em> are installed in</p>
<pre>
    /usr/local/pkgs/graft-2.16
    /usr/local/pkgs/perl-5.18.2
</pre>
<p> you can resolve this dilemma by executing the following commands:</p>
<pre>
    /usr/local/pkgs/perl-5.18.2/bin/perl /usr/local/pkgs/graft-2.16/bin/graft -i graft-2.16
    /usr/local/pkgs/perl-5.18.2/bin/perl /usr/local/pkgs/graft-2.16/bin/graft -i perl-5.18.2
</pre>
<p> This will<em> graft</em> both<em> Graft</em> and<em> Perl</em> from
 the default package installation directory (as specified by<strong>
 PACKAGEDIR</strong> in the <tt>Makefile</tt>) into your default target
 directory (as specified by<strong> TARGETDIR</strong> in the <tt>
Makefile</tt>).</p>
<p> If you don't wish to use the default directories you can use the
 following commands to<em> graft</em> the packages into <tt>/pkgs</tt>
 instead of <tt>/usr/local</tt> for example:</p>
<pre>
    /usr/local/pkgs/perl-5.18.2/bin/perl /usr/local/pkgs/graft-2.16/bin/graft -i -t /pkgs /usr/local/pkgs/graft-2.16
    /usr/local/pkgs/perl-5.18.2/bin/perl /usr/local/pkgs/graft-2.16/bin/graft -i -t /pkgs /usr/local/pkgs/perl-5.18.2
</pre>
<p> Now both<em> Graft</em> and<em> Perl</em> have been<em> grafted</em>
 and any other package can be<em> grafted</em> by executing the simpler
 command:</p>
<pre>
    graft -i <em>package</em>
</pre>
<p> The<em> Graft</em> distribution includes a program called <tt>
graftBootStrap.sh</tt> which allows you to easily<em> graft</em> both<em>
 Graft</em> and<em> Perl</em>. It can be found in the<em> contrib</em>
 directory of the distribution. Thanks to Gordon Rowell for providing
 it.</p>
<p> You may also find the <tt>-L</tt> command line option to be useful
 to programmatically determine where<em> Graft</em> expects to find<em>
 Perl</em> along with the default locations of its log file, target and
 package directories. See the <a href="#graft-L">Information</a> section
 below for details.</p>
<hr>
<h2><a name="using-graft">Using<em> Graft</em></a></h2>
<h3><a name="compiling-packages">Compiling Packages</a></h3>
<p> Any packages you wish to place under the control of<em> Graft</em>
 should be compiled and installed in such a way that any package
 dependent files are referenced with the ACTUAL package installation
 directory rather than the common area in which<em> Graft</em> will be
 creating symbolic links. For example, ensure that<em> Perl</em> version<em>
 5.18.2</em> is looking for its library files in <tt>
/usr/local/pkgs/perl-5.18.2/lib/perl5</tt> instead of <tt>
/usr/local/lib/perl5</tt>. This approach will allow you to easily
 separate multiple versions of the same package without any problems.</p>
<hr width="25%">
<h3><a name="usage"><em>Graft</em> command line options</a></h3>
<p> All of the details concerning actions, package locations and target
 directories are passed to<em> Graft</em> on the command line. (<em>
Graft</em> 1.<em>x</em> used a configuration file. This has now been
 deprecated in favour of a log file).</p>
<p><em> Graft</em>'s command line options can be summarised as:</p>
<pre>
    graft -i [-P|u] [-l log] [-n] [-v|V] [-r /rootdir] [-s|-t target] package(s)
    graft -d [-D] [-u] [-l log] [-n] [-v|V] [-r /rootdir] [-s|-t target] package(s)
    graft -p [-D] [-u] [-l log] [-n] [-v|V] [-r /rootdir] [-s|-t target] package(s)
    graft -L
</pre>
<p><em> Graft</em> has four basic actions:</p>
<ol>
<li>
<p> <a name="graft-i"><strong>Install</strong></a></p>
<pre>
    graft -i [-C] [-P|u] [-l log] [-n] [-v|V] [-r /rootdir] [-s|-t target] package(s)
</pre>
<dl>
<dt><strong> -i</strong></dt>
<dd>
<p> Install symbolic links from the package installation directory to
 the target directory. Requires superuser privileges if<strong>
 SUPERUSER</strong> was set to<strong> 1</strong> in the <tt>Makefile</tt>
.</p>
</dd>
<dt><strong> -C</strong></dt>
<dd>
<p> If<strong> NEVERGRAFT</strong> was set to<strong> 1</strong> in the <tt>
Makefile</tt>, disable the automatic exclusion of files and/or
 directories whose names exactly match the values specified by<strong>
 GRAFT-NEVER</strong> in the <tt>Makefile</tt>.</p>
<p> If<strong> NEVERGRAFT</strong> was set to<strong> 0</strong> in the <tt>
Makefile</tt>, force the automatic exclusion of files and/or directories
 whose names exactly match the values specified by<strong> GRAFT-NEVER</strong>
 in the <tt>Makefile</tt>.</p>
<p> Can only be used with the -i option.</p>
<p> This option is ignored for each<em> grafted</em> directory, if the
 directory contains a <tt>.nograft</tt> or <tt>.graft-include</tt> file.</p>
<p> The<em> Graft</em> manual page will correctly reflect the behaviour
 of this option based on the values specified in the <tt>Makefile</tt>.
 If there are no objects specified for<strong> GRAFT-NEVER</strong> then
 this option will be silently ignored and will not appear in the help
 message nor in the manual page.</p>
</dd>
<dt><strong> -P</strong></dt>
<dd>
<p> Preserve modes and ownerships when creating new directories or
 copying files if<strong> PRESERVEPERMS</strong> was set to<strong> 0</strong>
 in the <tt>Makefile</tt>. Do not preserve modes and ownerships if the
 option is not provided on the command line.</p>
<p> Do not preserve modes and ownerships when creating new directories
 or copying files if<strong> PRESERVEPERMS</strong> was set to<strong> 1</strong>
 in the <tt>Makefile</tt>. Preserve modes and ownerships if the option
 is not provided on the command line.</p>
<p> Cannot be used with the<strong> -u</strong> option.</p>
<p> This option will be silently ignored if the effective user of<em>
 Graft</em> is not root.</p>
<p> The<em> Graft</em> manual page will correctly reflect the behaviour
 of this option based on the values specified in the <tt>Makefile</tt>.
 This option will be silently ignored and will not appear in the help
 message nor in the manual page if<strong> SUPERUSER</strong> was set to<strong>
 0</strong> in the <tt>Makefile</tt>.</p>
</dd>
<dt><strong> -u</strong></dt>
<dd>
<p> Superuser privileges are not required when installing packages.</p>
<p> Cannot be used with the<strong> -P</strong> option.</p>
<p> This option is only available if<strong> SUPERUSER</strong> was set
 to<strong> 1</strong> in the <tt>Makefile</tt>.</p>
<p> The<em> Graft</em> manual page will correctly reflect the behaviour
 of this option based on the values specified in the <tt>Makefile</tt>.
 This option will be silently ignored and will not appear in the help
 message nor in the manual page if<strong> SUPERUSER</strong> was set to<strong>
 0</strong> in the <tt>Makefile</tt>.</p>
</dd>
<dt><strong> -l<em> log</em></strong></dt>
<dd>
<p> Specify an alternate log file instead of the default specified by<strong>
 LOGFILE</strong> in the <tt>Makefile</tt>. No logging is performed if
 the<strong> -n</strong> option is used.</p>
<p> Log entries have the form:</p>
<pre>
    878790215   1.10+   I    /usr/local/pkgs/cpio-2.4.2            /usr/local
    878888916   2.1     I    /usr/local/pkgs/gzip-1.2.4            /usr/local
    878888916   2.1     IC   /usr/local/pkgs/gzip-1.2.4/bin/gzip   invalid symlink
</pre>
<p> This shows that a development version of<em> graft</em> (1.10+) was
 used to install symbolic links from <tt>/usr/local/pkgs/cpio-2.4.2</tt>
 to <tt>/usr/local</tt>. A new version of<em> graft</em> (2.1) was used
 to install symbolic links from <tt>/usr/local/pkgs/gzip-1.2.4</tt> to <tt>
/usr/local</tt>. The <tt>IC</tt> entry indicates that a conflict
 occurred during this installation - the file <tt>
/usr/local/pkgs/bin/gzip</tt> was a symbolic link to something other
 than <tt>/usr/local/pkgs/gzip-1.2.4/bin/gzip</tt>.</p>
</dd>
<dt><strong> -n</strong></dt>
<dd>
<p> List actions but do not perform them. Implies the very verbose
 option. Does not require superuser privileges regardless of the value
 of<strong> SUPERUSER</strong> in the <tt>Makefile</tt>.</p>
</dd>
<dt><strong> -v</strong></dt>
<dd>
<p> Be verbose.</p>
</dd>
<dt><strong> -V</strong></dt>
<dd>
<p> Be very verbose.</p>
</dd>
<dt><strong> -r<em> /rootdir</em></strong></dt>
<dd>
<p> Use the fully qualified named directory as the root directory for
 all graft operations. The source directory, target directory and log
 file will all be relative to this specific directory.</p>
<p> Can only be used by the superuser.</p>
</dd>
<dt><strong> -s</strong></dt>
<dd>
<p><em> Stow</em>/<em>Depot</em> compatibility mode. Infer the<em> Graft</em>
 target directory from each package installation directory in the manner
 of<em> Stow</em> and<em> Depot</em>.</p>
<p> Target directory is the <tt>dirname</tt> of the <tt>dirname</tt> of
 the package installation directory. (Yes that really is two <tt>dirname</tt>
s). So if the package installation directory is</p>
<pre>
    /usr/local/depot/gzip-1.2.4
</pre>
<p> the package will be<em> grafted</em> into</p>
<pre>
    /usr/local
</pre>
<p> Cannot be used with the<strong> -t</strong> option.</p>
</dd>
<dt><strong> -t<em> target</em></strong></dt>
<dd>
<p> Override the default<em> graft</em> target directory with<strong><em>
 target</em></strong>. The value of<strong><em> target</em></strong>
 must be a fully qualified directory and it must exist.</p>
<p> Cannot be used with the<strong> -s</strong> option.</p>
</dd>
<dt><strong> package</strong></dt>
<dd>
<p> Install the named package. If<strong> package</strong> is a fully
 qualified directory, use it as the package installation directory. If<strong>
 package</strong> is not a fully qualified directory, prepend it with
 the value of<strong> PACKAGEDIR</strong> as specified in the <tt>
Makefile</tt>.</p>
</dd>
</dl>
<hr width="10%"></li>
<li>
<p> <a name="graft-d"><strong>Delete</strong></a></p>
<pre>
    graft -d [-D] [-u] [-l log] [-n] [-v|V] [-r /rootdir] [-s|-t target] package(s)
</pre>
<dl>
<dt><strong> -d</strong></dt>
<dd>
<p> Delete symbolic links from the package target directory to the
 package installation directory. Requires superuser privileges if<strong>
 SUPERUSER</strong> was set to<strong> 1</strong> in the <tt>Makefile</tt>
.</p>
</dd>
<dt><strong> -D</strong></dt>
<dd>
<p> Delete empty directories if<strong> DELETEOBJECTS</strong> was set
 to<strong> 0</strong> in the <tt>Makefile</tt>. If the option is not
 provided on the command line, notify the user that a directory has been
 emptied.</p>
<p> Do not delete empty directories if<strong> DELETEOBJECTS</strong>
 was set to<strong> 1</strong> in the <tt>Makefile</tt>. Notify the user
 that a directory has been emptied. If the option is not provided on the
 command line, delete empty directories.</p>
<p> The<em> Graft</em> manual page will correctly reflect the behaviour
 of this option based on the values specified in the <tt>Makefile</tt>.</p>
</dd>
<dt><strong> -u</strong></dt>
<dd>
<p> Superuser privileges are not required when deleting packages.</p>
<p> This option is only available if<strong> SUPERUSER</strong> was set
 to<strong> 1</strong> in the <tt>Makefile</tt>.</p>
<p> The<em> Graft</em> manual page will correctly reflect the behaviour
 of this option based on the values specified in the <tt>Makefile</tt>.
 This option will be silently ignored and will not appear in the help
 message nor in the manual page if<strong> SUPERUSER</strong> was set to<strong>
 0</strong> in the <tt>Makefile</tt>.</p>
</dd>
<dt><strong> -l<em> log</em></strong></dt>
<dd>
<p> Specify an alternate log file instead of the default specified by<strong>
 LOGFILE</strong> in the <tt>Makefile</tt>. No logging is performed if
 the<strong> -n</strong> option is used.</p>
<p> Log entries have the form:</p>
<pre>
    879126278       1.10+   D       /usr/local/pkgs/weblint-1.017     /usr/local
    879126278       1.10+   DC      /usr/local/pkgs/weblint-1.017/bin/weblint  file exists
    879126278       1.10+   DC      /usr/local/pkgs/weblint-1.017/man/man1/weblint.1  file exists
</pre>
<p> This shows that a development version of<em> graft</em> (1.10+) was
 used to delete symbolic links from <tt>/usr/local</tt> to <tt>
/usr/local/pkgs/weblint-1.017</tt>. The <tt>DC</tt> entries indicate
 that conflicts occurred during this action - the files <tt>
/usr/local/bin/weblint</tt> and <tt>/usr/local/man/man1/weblint.1</tt>
 already exist.</p>
</dd>
<dt><strong> -n</strong></dt>
<dd>
<p> List actions but do not perform them. Implies the very verbose
 option. Does not require superuser privileges regardless of the value
 of<strong> SUPERUSER</strong> in the <tt>Makefile</tt>.</p>
</dd>
<dt><strong> -v</strong></dt>
<dd>
<p> Be verbose.</p>
</dd>
<dt><strong> -V</strong></dt>
<dd>
<p> Be very verbose.</p>
</dd>
<dt><strong> -r<em> /rootdir</em></strong></dt>
<dd>
<p> Use the fully qualified named directory as the root directory for
 all graft operations. The source directory, target directory and log
 file will all be relative to this specific directory.</p>
<p> Can only be used by the superuser.</p>
</dd>
<dt><strong> -s</strong></dt>
<dd>
<p><em> Stow</em>/<em>Depot</em> compatibility mode. Infer the<em> Graft</em>
 target directory from each package installation directory in the manner
 of<em> Stow</em> and<em> Depot</em>.</p>
<p> Target directory is the <tt>dirname</tt> of the <tt>dirname</tt> of
 the package installation directory. (Yes that really is two <tt>dirname</tt>
s). So if the package installation directory is</p>
<pre>
    /usr/local/depot/gzip-1.2.4
</pre>
<p> the package will be<em> grafted</em> into</p>
<pre>
    /usr/local
</pre>
<p> Cannot be used with the<strong> -t</strong> option.</p>
</dd>
<dt><strong> -t<em> target</em></strong></dt>
<dd>
<p> Override the default<em> graft</em> target directory with<strong><em>
 target</em></strong>. The value of<strong><em> target</em></strong>
 must be a fully qualified directory and it must exist.</p>
<p> Cannot be used with the<strong> -s</strong> option.</p>
</dd>
<dt><strong> package</strong></dt>
<dd>
<p> Delete the named package. If<strong> package</strong> is a fully
 qualified directory, use it as the package installation directory. If<strong>
 package</strong> is not a fully qualified directory, prepend it with
 the value of<strong> PACKAGEDIR</strong> as specified in the <tt>
Makefile</tt>.</p>
</dd>
</dl>
<hr width="10%"></li>
<li>
<p> <a name="graft-p"><strong>Prune</strong></a></p>
<pre>
    graft -p [-D] [-u] [-l log] [-n] [-v|V] [-r /rootdir] [-s|-t target] package(s)
</pre>
<dl>
<dt><strong> -p</strong></dt>
<dd>
<p> Prune objects (files, links or directories) from the package target
 directory that are in conflict with the package installation directory.
 Requires superuser privileges if<strong> SUPERUSER</strong> was set to<strong>
 1</strong> in the <tt>Makefile</tt>.</p>
</dd>
<dt><strong> -D</strong></dt>
<dd>
<p> Remove conflicting objects if<strong> DELETEOBJECTS</strong> was set
 to<strong> 0</strong> in the <tt>Makefile</tt>. Rename conflicting
 objects as <tt><em>object</em>.pruned</tt> if the option is not
 provided on the command line.</p>
<p> Rename conflicting objects to <tt><em>object</em>.pruned</tt> if<strong>
 DELETEOBJECTS</strong> was set to<strong> 1</strong> in the <tt>
Makefile</tt>. Remove conflicting objects if the option is not provided
 in the command line.</p>
<p> If a directory is to be removed and it is not empty, it will be
 renamed as <tt><em>dir</em>.pruned</tt> and a suitable warning message
 will be given regardless of the sense of this flag.</p>
<p> The<em> Graft</em> manual page will correctly reflect the behaviour
 of this option based on the values specified in the <tt>Makefile</tt>.</p>
</dd>
<dt><strong> -u</strong></dt>
<dd>
<p> Superuser privileges are not required when pruning packages.</p>
<p> This option is only available if<strong> SUPERUSER</strong> was set
 to<strong> 1</strong> in the <tt>Makefile</tt>.</p>
<p> The<em> Graft</em> manual page will correctly reflect the behaviour
 of this option based on the values specified in the <tt>Makefile</tt>.
 This option will be silently ignored and will not appear in the help
 message nor in the manual page if<strong> SUPERUSER</strong> was set to<strong>
 0</strong> in the <tt>Makefile</tt>.</p>
</dd>
<dt><strong> -l<em> log</em></strong></dt>
<dd>
<p> Specify an alternate log file instead of the default specified by<strong>
 LOGFILE</strong> in the <tt>Makefile</tt>. No logging is performed if
 the<strong> -n</strong> option is used.</p>
<p> Log entries have the form:</p>
<pre>
    879126283       1.10+   P       /usr/local/pkgs/weblint-1.017     /usr/local
</pre>
<p> This shows that a development version of<em> graft</em> (1.10+) was
 used to delete objects from <tt>/usr/local</tt> that were in conflict
 with <tt>/usr/local/pkgs/weblint-1.017</tt>.</p>
</dd>
<dt><strong> -n</strong></dt>
<dd>
<p> List actions but do not perform them. Implies the very verbose
 option. Does not require superuser privileges regardless of the value
 of<strong> SUPERUSER</strong> in the <tt>Makefile</tt>.</p>
</dd>
<dt><strong> -v</strong></dt>
<dd>
<p> Be verbose.</p>
</dd>
<dt><strong> -V</strong></dt>
<dd>
<p> Be very verbose.</p>
</dd>
<dt><strong> -r<em> /rootdir</em></strong></dt>
<dd>
<p> Use the fully qualified named directory as the root directory for
 all graft operations. The source directory, target directory and log
 file will all be relative to this specific directory.</p>
<p> Can only be used by the superuser.</p>
</dd>
<dt><strong> -s</strong></dt>
<dd>
<p><em> Stow</em>/<em>Depot</em> compatibility mode. Infer the<em> Graft</em>
 target directory from each package installation directory in the manner
 of<em> Stow</em> and<em> Depot</em>.</p>
<p> Target directory is the <tt>dirname</tt> of the <tt>dirname</tt> of
 the package installation directory. (Yes that really is two <tt>dirname</tt>
s). So if the package installation directory is</p>
<pre>
    /usr/local/depot/gzip-1.2.4
</pre>
<p> the package will be<em> grafted</em> into</p>
<pre>
    /usr/local
</pre>
<p> Cannot be used with the<strong> -t</strong> option.</p>
</dd>
<dt><strong> -t<em> target</em></strong></dt>
<dd>
<p> Override the default<em> graft</em> target directory with<strong><em>
 target</em></strong>. The value of<strong><em> target</em></strong>
 must be a fully qualified directory and it must exist.</p>
<p> Cannot be used with the<strong> -s</strong> option.</p>
</dd>
<dt><strong> package</strong></dt>
<dd>
<p> Prune the named package. If<strong> package</strong> is a fully
 qualified directory, use it as the package installation directory. If<strong>
 package</strong> is not a fully qualified directory, prepend it with
 the value of<strong> PACKAGEDIR</strong> as specified in the <tt>
Makefile</tt>.</p>
</dd>
</dl>
</li>
<li>
<p> <a name="graft-L"><strong>Information</strong></a></p>
<pre>
    graft -L
</pre>
<dl>
<dt><strong> -L</strong></dt>
<dd>
<p> This is a special mode and it overrides all other command line
 arguments. When present<strong> graft</strong> will display the<strong>
 default</strong> locations for Perl, the graft log file, the target
 directory, and the package directory in a form suitable for creating
 environment variables for Bourne like shells. The output will appear on<strong>
 STDOUT</strong> as follows:</p>
<pre>
    GRAFT_PERL=/usr/bin/perl
    GRAFT_LOGFILE=/var/log/graft
    GRAFT_TARGETDIR=/usr/local
    GRAFT_PACKAGEDIR=/usr/local/pkgs
</pre>
<p> You can set these environment variables using one of the following
 methods.</p>
<pre>
    eval &quot;$(graft -L)&quot;    # modern shells such as bash, zsh etc
    eval &quot;`graft -L`&quot;     # older shells such as sh etc
</pre>
</dd>
</dl>
</li>
</ol>
<hr width="25%">
<h3><a name="testing">Testing the<em> Graft</em> Installation</a></h3>
<p> Before creating the symbolic links from the target directory to the
 package directory, you may wish to see what actions<em> Graft</em> will
 perform. Execute the following command:</p>
<pre>
    graft -i -n <em>package-name</em>
</pre>
<p> The <tt>-i</tt> option tells<em> Graft</em> to install the package
 and the <tt>-n</tt> option tells<em> Graft</em> to report on its
 actions without actually performing them. The default<em> Graft</em>
 target directory will be used and the package installation directory
 will be taken from the fully qualified package argument or the default
 value will be prepended to the package argument if it is not fully
 qualified.</p>
<p><em> Graft</em> will report on the following actions:</p>
<ul>
<li>
<p> Installing links to<em> package-location</em> in<em> package-target</em>
</p>
<p> Indicates the real package location and its<em> grafted</em> target.</p>
</li>
<li>
<p> Processing<em> package-directory</em></p>
<p> Indicates which package directory is being processed.</p>
</li>
<li>
<p> MKDIR<em> dirname</em></p>
<p> This destination directory will be created.</p>
</li>
<li>
<p> SYMLINK<em> dest-package-file</em> -&gt;<em> package-file</em></p>
<p> This symbolic link will be created.</p>
</li>
<li>
<p> NOP<em> string</em></p>
<p> No action was necessary for this package object.</p>
</li>
<li>
<p> BYPASS<em> dirname</em> - .nograft file found</p>
<p> This directory contains a file called <tt>.nograft</tt> so its
 contents and any subdirectories will be bypassed by<em> Graft</em>.</p>
</li>
<li>
<p> READING include file<em> package-dir</em><tt>/.graft-include</tt></p>
<p> The directory currently being processed by<em> Graft</em> contains a
 file called <tt>.graft-include</tt> which contains a list of file
 and/or directory names from the directory that should only be<em>
 grafted</em>. The contents of this file are being read by<em> Graft</em>
.</p>
</li>
<li>
<p> INCLUDE file<em> package-file</em> - listed in<em> package-dir</em><tt>
/.graft-include</tt></p>
<p> The file name mentioned in this message appears in the<em>
 .graft-include</em> file and the file exists in the directory currently
 being processed. It will be <tt>grafted</tt>.</p>
</li>
<li>
<p> IGNORE file<em> package-file</em> - not listed in<em> package-dir</em><tt>
/.graft-include</tt></p>
<p> The file name mentioned in this message does not appear in the<em>
 .graft-include</em> file and the file exists in the directory currently
 being processed. It will not be <tt>grafted</tt>.</p>
</li>
<li>
<p> INCLUDE directory<em> package-directory</em> - listed in<em>
 package-dir</em><tt>/.graft-include</tt></p>
<p> The directory name mentioned in this message appears in the<em>
 .graft-include</em> file and the directory exists in the directory
 currently being processed. It will be <tt>grafted</tt>.</p>
</li>
<li>
<p> IGNORE directory<em> package-file</em> - not listed in<em>
 package-dir</em><tt>/.graft-include</tt></p>
<p> The directory name mentioned in this message does not appear in the<em>
 .graft-include</em> file and the directory exists in the directory
 currently being processed. It will not be <tt>grafted</tt>.</p>
</li>
<li>
<p> READING exclude file<em> package-dir</em><tt>/.graft-exclude</tt></p>
<p> The directory currently being processed by<em> Graft</em> contains a
 file called <tt>.graft-exclude</tt> which contains a list of file
 and/or directory names from the directory that should not be<em>
 grafted</em>. The contents of this file are being read by<em> Graft</em>
.</p>
</li>
<li>
<p> IGNORE include file<em> package-dir</em><tt>/.graft-include</tt>,
 overridden by exclude file<em> package-dir</em><tt>/.graft-exclude</tt></p>
<p> The directory currently being processed by<em> Graft</em> contains a
 file called <tt>.graft-exclude</tt> as well as a file called <tt>
.graft-include</tt>. The <tt>.graft-exclude</tt> file takes precedence
 over the <tt>.graft-include</tt> file, so the latter file will be
 ignored.</p>
</li>
<li>
<p> EXCLUDE file<em> package-file</em> - listed in<em> package-dir</em><tt>
/.graft-exclude</tt></p>
<p> The file name mentioned in this message appears in the<em>
 .graft-exclude</em> file and the file exists in the directory currently
 being processed. It will not be <tt>grafted</tt>.</p>
</li>
<li>
<p> EXCLUDE directory<em> package-directory</em> - listed in<em>
 package-dir</em><tt>/.graft-exclude</tt></p>
<p> The directory name mentioned in this message appears in the<em>
 .graft-exclude</em> file and the directory exists in the directory
 currently being processed. It will not be <tt>grafted</tt>.</p>
</li>
<li>
<p> CONFLICT<em> message</em></p>
<p><em> Graft</em> could not successfully process a package object. One
 of the following conditions was encountered:</p>
<ul>
<li> The package object is a directory and the target object exists but
 it not a directory.</li>
<li> The package object is not a directory and the target object exists
 and is not a symbolic link.</li>
<li> The package object is not a directory and the target object exists
 and is a symbolic link to something other than the package object.</li>
</ul>
<p> Conflicts are ALWAYS reported on standard error. If you wish to see
 if the installation of a package will have any conflicts, you can
 execute:</p>
<pre>
    graft -i -n <em>package-name</em> &gt; /dev/null
</pre>
<p> Only <tt>CONFLICT</tt> messages will be displayed. If nothing is
 displayed then you can safely conclude that this package can be
 installed using<em> Graft</em> without any conflicts.</p>
</li>
</ul>
<p> If you were to test the installation of the<em> kermit-5A190</em>
 package you would execute the command:</p>
<pre>
    graft -i -n kermit-5A190
</pre>
 You should see output resembling:
<pre>
    Installing   links to /usr/local/pkgs/kermit-5A190 in /usr/local
    Processing   /usr/local/pkgs/kermit-5A190
    SYMLINK      /usr/local/README -&gt; /usr/local/pkgs/kermit-5A190/README
    NOP          /usr/local/pkgs/kermit-5A190/bin and /usr/local/bin are both directories
    Processing   /usr/local/pkgs/kermit-5A190/bin
    SYMLINK      /usr/local/bin/kermit -&gt; /usr/local/pkgs/kermit-5A190/bin/kermit
    SYMLINK      /usr/local/bin/wart -&gt; /usr/local/pkgs/kermit-5A190/bin/wart
    NOP          /usr/local/pkgs/kermit-5A190/man and /usr/local/man are both directories
    Processing   /usr/local/pkgs/kermit-5A190/man
    NOP          /usr/local/pkgs/kermit-5A190/man/man1 and /usr/local/man/man1 are both directories
    Processing   /usr/local/pkgs/kermit-5A190/man/man1
    SYMLINK      /usr/local/man/man1/kermit.1 -&gt; /usr/local/pkgs/kermit-5A190/man/man1/kermit.1
    MKDIR        /usr/local/doc
    Processing   /usr/local/pkgs/kermit-5A190/doc
    SYMLINK      /usr/local/doc/ckccfg.doc -&gt; /usr/local/pkgs/kermit-5A190/doc/ckccfg.doc
    SYMLINK      /usr/local/doc/ckuins.doc -&gt; /usr/local/pkgs/kermit-5A190/doc/ckuins.doc
    SYMLINK      /usr/local/doc/ckc190.upd -&gt; /usr/local/pkgs/kermit-5A190/doc/ckc190.upd
    SYMLINK      /usr/local/doc/ckcker.upd -&gt; /usr/local/pkgs/kermit-5A190/doc/ckcker.upd
    SYMLINK      /usr/local/doc/ckaaaa.hlp -&gt; /usr/local/pkgs/kermit-5A190/doc/ckaaaa.hlp
    SYMLINK      /usr/local/doc/ckuaaa.hlp -&gt; /usr/local/pkgs/kermit-5A190/doc/ckuaaa.hlp
    NOP          /usr/local/pkgs/kermit-5A190/lib and /usr/local/lib are both directories
    Processing   /usr/local/pkgs/kermit-5A190/lib
    SYMLINK      /usr/local/lib/ckedemo.ini -&gt; /usr/local/pkgs/kermit-5A190/lib/ckedemo.ini
    SYMLINK      /usr/local/lib/ckeracu.ini -&gt; /usr/local/pkgs/kermit-5A190/lib/ckeracu.ini
    SYMLINK      /usr/local/lib/ckermit.ini -&gt; /usr/local/pkgs/kermit-5A190/lib/ckermit.ini
    SYMLINK      /usr/local/lib/ckermod.ini -&gt; /usr/local/pkgs/kermit-5A190/lib/ckermod.ini
    SYMLINK      /usr/local/lib/cketest.ini -&gt; /usr/local/pkgs/kermit-5A190/lib/cketest.ini
    SYMLINK      /usr/local/lib/ckevt.ini -&gt; /usr/local/pkgs/kermit-5A190/lib/ckevt.ini
    SYMLINK      /usr/local/lib/ckurzsz.ini -&gt; /usr/local/pkgs/kermit-5A190/lib/ckurzsz.ini
</pre>
<p> This output shows you that most of the directories already exist
 (indicated by the <tt>NOP</tt> flags). A symbolic link will be created
 in the relevant target directory to each of the files in the<em>
 kermit-5A190</em> package. One directory exists in the<em> kermit-5A190</em>
 package that does not exist in the target - <tt>doc</tt>. This
 directory will be created by<em> Graft</em>.</p>
<p><strong> NOTE</strong>: If you are using the<em> automounter</em> you
 may not be able to create the directory <tt>/usr/local/doc</tt>. You'll
 have to create the directory on the NFS server under the file system in
 which it really lives. You should be familiar with the peculiarities of
 the<em> automounter</em> and your specific site configuration before
 creating any directories directly under mount points used by the<em>
 automounter</em>.</p>
<hr width="25%">
<h3><a name="installing-packages">Installing Packages</a></h3>
<p> Once you have ensured that<em> Graft</em> will perform the correct
 actions, you can execute:</p>
<pre>
    graft -i <em>package-name</em>
</pre>
<p> So to install<em> kermit</em> you would execute:</p>
<pre>
    graft -i kermit-5A190
</pre>
<p> There will be no output from<em> Graft</em> unless it encounters a
 conflict. If you wish to see more information you can specify one of
 the verbose flags. For a minimum of output you can execute:</p>
<pre>
    graft -i -v kermit-5A190
</pre>
<p> You should see the following output:</p>
<pre>
    Processing   /usr/local/pkgs/kermit-5A190
    Processing   /usr/local/pkgs/kermit-5A190/bin
    Processing   /usr/local/pkgs/kermit-5A190/man
    Processing   /usr/local/pkgs/kermit-5A190/man/man1
    Processing   /usr/local/pkgs/kermit-5A190/doc
    Processing   /usr/local/pkgs/kermit-5A190/lib
</pre>
<p> If you choose the very verbose option by executing:</p>
<pre>
    graft -i -V kermit-5A190
</pre>
<p> the output will be the same as that when the <tt>-n</tt> option was
 used, however this time<em> Graft</em> will actually create the
 symbolic links.</p>
<pre>
    Installing   links to /usr/local/pkgs/kermit-5A190 in /usr/local
    Processing   /usr/local/pkgs/kermit-5A190
    SYMLINK      /usr/local/README -&gt; /usr/local/pkgs/kermit-5A190/README
    NOP          /usr/local/pkgs/kermit-5A190/bin and /usr/local/bin are both directories
    Processing   /usr/local/pkgs/kermit-5A190/bin
    SYMLINK      /usr/local/bin/kermit -&gt; /usr/local/pkgs/kermit-5A190/bin/kermit
    SYMLINK      /usr/local/bin/wart -&gt; /usr/local/pkgs/kermit-5A190/bin/wart
    NOP          /usr/local/pkgs/kermit-5A190/man and /usr/local/man are both directories
    Processing   /usr/local/pkgs/kermit-5A190/man
    NOP          /usr/local/pkgs/kermit-5A190/man/man1 and /usr/local/man/man1 are both directories
    Processing   /usr/local/pkgs/kermit-5A190/man/man1
    SYMLINK      /usr/local/man/man1/kermit.1 -&gt; /usr/local/pkgs/kermit-5A190/man/man1/kermit.1
    NOP          /usr/local/pkgs/kermit-5A190/doc and /usr/local/doc are both directories
    Processing   /usr/local/pkgs/kermit-5A190/doc
    SYMLINK      /usr/local/doc/ckccfg.doc -&gt; /usr/local/pkgs/kermit-5A190/doc/ckccfg.doc
    SYMLINK      /usr/local/doc/ckuins.doc -&gt; /usr/local/pkgs/kermit-5A190/doc/ckuins.doc
    SYMLINK      /usr/local/doc/ckc190.upd -&gt; /usr/local/pkgs/kermit-5A190/doc/ckc190.upd
    SYMLINK      /usr/local/doc/ckcker.upd -&gt; /usr/local/pkgs/kermit-5A190/doc/ckcker.upd
    SYMLINK      /usr/local/doc/ckaaaa.hlp -&gt; /usr/local/pkgs/kermit-5A190/doc/ckaaaa.hlp
    SYMLINK      /usr/local/doc/ckuaaa.hlp -&gt; /usr/local/pkgs/kermit-5A190/doc/ckuaaa.hlp
    NOP          /usr/local/pkgs/kermit-5A190/lib and /usr/local/lib are both directories
    Processing   /usr/local/pkgs/kermit-5A190/lib
    SYMLINK      /usr/local/lib/ckedemo.ini -&gt; /usr/local/pkgs/kermit-5A190/lib/ckedemo.ini
    SYMLINK      /usr/local/lib/ckeracu.ini -&gt; /usr/local/pkgs/kermit-5A190/lib/ckeracu.ini
    SYMLINK      /usr/local/lib/ckermit.ini -&gt; /usr/local/pkgs/kermit-5A190/lib/ckermit.ini
    SYMLINK      /usr/local/lib/ckermod.ini -&gt; /usr/local/pkgs/kermit-5A190/lib/ckermod.ini
    SYMLINK      /usr/local/lib/cketest.ini -&gt; /usr/local/pkgs/kermit-5A190/lib/cketest.ini
    SYMLINK      /usr/local/lib/ckevt.ini -&gt; /usr/local/pkgs/kermit-5A190/lib/ckevt.ini
    SYMLINK      /usr/local/lib/ckurzsz.ini -&gt; /usr/local/pkgs/kermit-5A190/lib/ckurzsz.ini
</pre>
<p><strong> NOTE</strong>: In this case the <tt>/usr/local/doc</tt>
 directory was not created by<em> Graft</em> because <tt>/usr/local</tt>
 is a mount point controlled by the<em> automounter</em>. The <tt>doc</tt>
 directory was created manually prior to executing<em> Graft</em>.</p>
<hr width="25%">
<h3><a name="bypass">Bypassing package directories</a></h3>
<p> You may have the need to place only part of a package under the
 control of<em> Graft</em>. Examples of such occasions may be:</p>
<ul>
<li>
<p> The contents of one package conflict with another package. For
 example <tt>/usr/local/pkgs/gcc-2.7.2.1/lib/libiberty.a</tt> and <tt>
/usr/local/pkgs/gdb-4.16/lib/libiberty.a</tt>.</p>
</li>
<li>
<p> A package directory is obviously the exclusive domain of the package
 and no benefit will be gained by creating symbolic links to its files.
 For example <tt>/usr/local/pkgs/perl-5.18.2/lib/perl5</tt>.</p>
<p><strong> NOTE</strong>: This will ONLY work if you originally
 compiled and installed the package such that it refers to its files by
 their '<em>real</em>' pathnames and NOT by the virtual pathnames
 provided by<em> Graft</em>.</p>
</li>
</ul>
<p> You can force<em> Graft</em> to bypass a directory by creating the
 file</p>
<pre>
    <em>package-name/dir/dir/</em>.nograft
</pre>
<p> Using the second example above, if you were to create the file:</p>
<pre>
    /usr/local/pkgs/perl-5.18.2/lib/perl5/.nograft
</pre>
<p><em> Graft</em> would create directories and symbolic links for every
 file and directory down to <tt>/usr/local/pkgs/perl-5.18.2/lib</tt>.
 The <tt>perl5</tt> directory and anything below it would not be
 created.</p>
<hr width="25%">
<h3><a name="include">Including specific files and/or directories</a></h3>
<p> There may be the occasional need to include specific files and/or
 directories in a directory, rather than the entire directory tree
 itself. An example of such an occurrence would be the case where a
 package contains a number of subdirectories, only one of which is
 required to be<em> grafted</em>.</p>
<p> You can force<em> Graft</em> to only include any number of files
 and/or directories in a package directory by creating the file</p>
<pre>
    .graft-include
</pre>
<p> in the same directory.</p>
<p> <tt>.graft-include</tt> will contain a list of file and/or directory
 names - one per line - of the files and/or directories you wish to
 include.</p>
<p> Consider the<em> a2ps</em> package for example. When installed it
 contains the following directories:</p>
<pre>
    /usr/local/pkgs/a2ps-4.13b/bin
    /usr/local/pkgs/a2ps-4.13b/etc
    /usr/local/pkgs/a2ps-4.13b/include
    /usr/local/pkgs/a2ps-4.13b/info
    /usr/local/pkgs/a2ps-4.13b/lib
    /usr/local/pkgs/a2ps-4.13b/man
    /usr/local/pkgs/a2ps-4.13b/share
</pre>
<p> The only directory you wish to<em> graft</em> is the <tt>bin</tt>
 directory. You could place a <tt>.nograft</tt> file in each of the
 other directories,<strong> OR</strong> you could create a single <tt>
.graft-include</tt> file in <tt>
/usr/local/pkgs/a2ps-4.13b/.graft-include</tt>. This file would contain</p>
<pre>
    bin
</pre>
<p> Now only the <tt>bin</tt> directory will be<em> grafted</em>.</p>
<hr width="25%">
<h3><a name="exclude">Excluding specific files and/or directories</a></h3>
<p> There may be the occasional need to exclude specific files and/or
 directories from a directory, rather than the entire directory itself.
 An example of such an occurrence would be the case where files from
 different packages have the same name.<em> Emacs</em> and<em> Xemacs</em>
 use the same names for a number of their configuration files for
 example.</p>
<p> You can force<em> Graft</em> to exclude any number of files and/or
 directories from a package directory by creating the file</p>
<pre>
    .graft-exclude
</pre>
<p> in the same directory.</p>
<p> <tt>.graft-exclude</tt> will contain a list of file and/or directory
 names - one per line - of the files and/or directories you wish to
 exclude.</p>
<p> For example, if you did not wish the file</p>
<pre>
    /usr/local/pkgs/sudo-1.5.3/etc/sudoers
</pre>
<p> to be<em> grafted</em> as</p>
<pre>
    /usr/local/etc/sudoers
</pre>
<p> but you did want</p>
<pre>
    /usr/local/pkgs/sudo-1.5.3/etc/visudo
</pre>
<p> to be<em> grafted</em> as</p>
<pre>
    /usr/local/etc/visudo
</pre>
<p> you would create the file</p>
<pre>
    /usr/local/pkgs/sudo-1.5.3/etc/.graft-exclude
</pre>
<p> and ensure its contents contained the line:</p>
<pre>
    sudoers
</pre>
<p><strong> NOTE:</strong> Any entries made in a <tt>.graft-exclude</tt>
 file will override the same entries made in a <tt>.graft-include</tt>
 file. That is, if a file or directory name is listen in both a <tt>
.graft-exclude</tt> and a <tt>.graft-include</tt> file, it will be<strong>
 excluded</strong> from the<em> graft</em>.</p>
<hr width="25%">
<h3><a name="config_dirs">Grafting configuration files</a></h3>
<p> Beginning with<em> Graft</em> 2.11 there is now the ability to treat
 a package directory as a repository for configuration files. In this
 case you would place a <tt>.graft-config</tt> file in the package
 directory and any files in that directory would be<strong> copied</strong>
 to the target directory. Files in conflict would also be copied but
 would have a default suffix of<em> .new</em> to ensure the existing
 file is not clobbered. Conflict discovery is achieved using a simple
 32-bit CRC check. This feature has been added to assist operating
 system distributors manage system configuration files, specifically it
 was added at the request of the maintainer of the <a href="http://www.dragora.org/">
Dragora GNU/Linux</a> distribution.</p>
<p> Consider the following example. You may wish to upgrade the<em>
 openssh</em> server as part of an upgrade to your distribution. In
 order to preserve any local user modifications to the relevant
 configuration files you would add a <tt>.graft-config</tt> file to the
 package as follows:</p>
<pre>
    /usr/local/pkgs/openssh-server-6.61/etc/default/.graft-config
    /usr/local/pkgs/openssh-server-6.61/etc/init.d/.graft-config
    /usr/local/pkgs/openssh-server-6.61/etc/init/.graft-config
    /usr/local/pkgs/openssh-server-6.61/etc/network/if-up.d/.graft-config
    /usr/local/pkgs/openssh-server-6.61/etc/pam.d/.graft-config
    /usr/local/pkgs/openssh-server-6.61/etc/ufw/applications.d/.graft-config
    /usr/local/pkgs/openssh-server-6.61/lib/systemd/system/.graft-config
</pre>
<p> The other directories in the distribution would not require any
 control files.</p>
<p> Imagine that the local administrator has made some changes to <tt>
/etc/pam.d/sshd</tt> such as adding additional authentication methods to
 support two-factor authentication for example. As the distribution
 maintainer you do not want to reverse this local change so when the
 local administrator upgrades the distribution,<em> Graft</em><strong>
 copies</strong> the new <tt>/etc/pam.d/sshd</tt> file to <tt>
/etc/pam.d/sshd.new</tt> which allows the local administrator to merge
 their changes with any new features supported by the upgrade.</p>
<p> To take full advantage of this feature you may need to explicitly
 set the target directory as follows:</p>
<pre>
    graft -i -t / openssh-server-6.61
</pre>
<hr width="25%">
<h3><a name="partial-graft">Grafting part of a package</a></h3>
<p> Some packages can be successfully used when only part of their
 installation directory is<em> grafted</em>. Other packages are
 recalcitrant and need some special hand holding which can only be
 solved by<em> grafting</em> each section of the package separately.</p>
<p> The first scenario can be handled by either <tt>.nograft</tt> files
 or partial<em> grafts</em>. Consider<em> Perl</em> version<em> 5.18.2</em>
. When installed in its own directory</p>
<pre>
    /usr/local/pkgs/perl-5.18.2
</pre>
<p> there are three subdirectories</p>
<pre>
    drwxr-sr-x   2 psamuel  bisg         512 Oct 30  1996 bin
    drwxr-sr-x   3 psamuel  bisg         512 Oct 30  1996 lib
    drwxr-sr-x   4 psamuel  bisg         512 Oct 30  1996 man
</pre>
<p> Everything in the <tt>lib</tt> directory is exclusive to<em> Perl</em>
 and does not require<em> grafting</em>. Therefore,<em> perl-5.18.2</em>
 can be<em> grafted</em> using either of the following two methods:</p>
<pre>
    touch /usr/local/pkgs/perl-5.18.2/lib/.nograft
    graft -i perl-5.18.2
</pre>
 or
<pre>
    graft -it /usr/local/bin perl-5.18.2/bin
    graft -it /usr/local/man perl-5.18.2/man
</pre>
<p> Now let's consider a recalcitrant package -<em> ObjectStore</em>
 version 4.0.2.a.0. When installed in</p>
<pre>
    /usr/local/pkgs/ostore-4.0.2.a.0
</pre>
<p> the following files and directories are available:</p>
<pre>
    -rwxrwxr-x   1 pauln    one3        1089 Oct 31  1996 Copyright
    drwxrwxrwx   8 pauln    one3         512 Oct  2  1996 common
    drwxrwxrwx   6 pauln    one3         512 Oct 31  1996 sunpro
    -rw-r-----   1 root     one3     1900544 Apr 29  1997 txn.log
</pre>
<p> The executable programs that need to be<em> grafted</em> are in <tt>
sunpro/bin</tt> and the manual pages that need to be<em> grafted</em>
 are in <tt>common/man</tt>. Everything else in the package does not
 need to be<em> grafted</em>. If the entire package was to be<em>
 grafted</em> the result would be two directories that are not in the
 regular<strong> $PATH</strong> and<strong> $MANPATH</strong>
 environment variables - namely <tt>/usr/local/common/man</tt> and <tt>
/usr/local/sunpro/bin</tt>, plus a host of other directories that are
 not relevant for<em> grafting</em>. No amount of <tt>.nograft</tt> and <tt>
.graft-exclude</tt> juggling will solve this problem.</p>
<p> The solution is to use two partial<em> grafts</em>:</p>
<pre>
    graft -it /usr/local/bin ostore-4.0.2.a.0/sunpro/bin
    graft -it /usr/local/man ostore-4.0.2.a.0/common/bin
</pre>
<p> Using this approach, the correct executables and manual pages are
 available without the need to<em> graft</em> unnecessary files and
 directories.</p>
<hr width="25%">
<h3><a name="deleting-packages">Deleting and/or Upgrading Packages</a></h3>
<p> If you wish to upgrade a package - let's assume you wish to upgrade<em>
 kermit</em> from version 5A190 to version 6.0.192 - you'd follow these
 steps.</p>
<p> Firstly, you'd compile and install<em> kermit-6.0.192</em> in</p>
<pre>
    /usr/local/pkgs/kermit-6.0.192
</pre>
<p> Once you'd tested it to your satisfaction, you'd need to delete the
 symbolic links to the current<em> grafted</em> version. You can check
 which actions<em> Graft</em> will perform by executing:</p>
<pre>
    graft -d -n kermit-5A190
</pre>
<p> You'll see output similar to</p>
<pre>
    Uninstalling links from /usr/local to /usr/local/pkgs/kermit-5A190
    Processing   /usr/local/pkgs/kermit-5A190
    Processing   /usr/local/pkgs/kermit-5A190/bin
    UNLINK       /usr/local/bin/kermit
    UNLINK       /usr/local/bin/wart
    Processing   /usr/local/pkgs/kermit-5A190/man
    Processing   /usr/local/pkgs/kermit-5A190/man/man1
    UNLINK       /usr/local/man/man1/kermit.1
    Processing   /usr/local/pkgs/kermit-5A190/doc
    UNLINK       /usr/local/doc/ckccfg.doc
    UNLINK       /usr/local/doc/ckuins.doc
    UNLINK       /usr/local/doc/ckc190.upd
    UNLINK       /usr/local/doc/ckcker.upd
    UNLINK       /usr/local/doc/ckaaaa.hlp
    UNLINK       /usr/local/doc/ckuaaa.hlp
    Processing   /usr/local/pkgs/kermit-5A190/lib
    UNLINK       /usr/local/lib/ckedemo.ini
    UNLINK       /usr/local/lib/ckeracu.ini
    UNLINK       /usr/local/lib/ckermit.ini
    UNLINK       /usr/local/lib/ckermod.ini
    UNLINK       /usr/local/lib/cketest.ini
    UNLINK       /usr/local/lib/ckevt.ini
    UNLINK       /usr/local/lib/ckurzsz.ini
    UNLINK       /usr/local/lib/.testing
</pre>
<p> If you're happy with the output from the test deletion you can
 delete the<em> grafted</em> package. Once again, you'll only see output
 if a failure occurs unless you use one of the verbose options.</p>
<p> If you execute:</p>
<pre>
    graft -dV kermit-5A190
</pre>
<p> you'll see:</p>
<pre>
    Uninstalling links from /usr/local to /usr/local/pkgs/kermit-5A190
    Processing   /usr/local/pkgs/kermit-5A190
    Processing   /usr/local/pkgs/kermit-5A190/bin
    UNLINK       /usr/local/bin/kermit
    UNLINK       /usr/local/bin/wart
    Processing   /usr/local/pkgs/kermit-5A190/man
    Processing   /usr/local/pkgs/kermit-5A190/man/man1
    UNLINK       /usr/local/man/man1/kermit.1
    Processing   /usr/local/pkgs/kermit-5A190/doc
    UNLINK       /usr/local/doc/ckccfg.doc
    UNLINK       /usr/local/doc/ckuins.doc
    UNLINK       /usr/local/doc/ckc190.upd
    UNLINK       /usr/local/doc/ckcker.upd
    UNLINK       /usr/local/doc/ckaaaa.hlp
    UNLINK       /usr/local/doc/ckuaaa.hlp
    EMPTY        /usr/local/doc is now empty. Delete manually if necessary.
    Processing   /usr/local/pkgs/kermit-5A190/lib
    UNLINK       /usr/local/lib/ckedemo.ini
    UNLINK       /usr/local/lib/ckeracu.ini
    UNLINK       /usr/local/lib/ckermit.ini
    UNLINK       /usr/local/lib/ckermod.ini
    UNLINK       /usr/local/lib/cketest.ini
    UNLINK       /usr/local/lib/ckevt.ini
    UNLINK       /usr/local/lib/ckurzsz.ini
</pre>
<p><strong> NOTE</strong>: In this case the existence of an empty
 directory has been discovered. If<em> Graft</em> empties a directory
 during a package deletion, it will either notify you or delete the
 directory depending on the combination of variables in the <tt>Makefile</tt>
 and command line options. It's probably better practise not to
 automatically delete empty directories as they may be used by other
 packages - such as lock file directories for example.</p>
<p> Now you can remove the<em> real</em> package contents. (You may not
 wish to do this immediately as some legacy systems may depend on
 features provided by the older version or you may feel the need for
 further testing before feeling confident that the old version can be
 removed):</p>
<pre>
    rm -rf /usr/local/pkgs/kermit-5A190
</pre>
<p> Now you can<em> graft</em> the new version of<em> kermit</em>.
 Execute:</p>
<pre>
    graft -i -n kermit-6.0.192
</pre>
<p> to ensure that the<em> grafting</em> will proceed without error.
 Once you are satisfied that this is the case you can<em> graft</em> the
 new package by executing:</p>
<pre>
    graft -i kermit-6.0.192
</pre>
<hr width="25%">
<h3><a name="transitioning">Transitioning a package to<em> Graft</em>
 control</a></h3>
<p><em> Graft</em> can be used to easily transition a package from its
 current installation in your target directory to a<em> grafted</em>
 installation.</p>
<p> As an example, let's consider the package<em> weblint</em> version
 1.017. It consists of three files installed in:</p>
<pre>
    /usr/local/bin/weblint
    /usr/local/lib/global.weblintrc
    /usr/local/man/man1/weblint.1
</pre>
<p> The first step is to create a new copy of the package in its own
 directory:</p>
<pre>
    /usr/local/pkgs/weblint-1.017
</pre>
<p> Ensure that any references to library files are now made to <tt>
/usr/local/pkgs/weblint-1.017/lib</tt> instead of <tt>/usr/local/lib</tt>
.</p>
<p> Test the new installation to ensure it behaves as expected.</p>
<p> Then prune the old files from <tt>/usr/local/*</tt> using:</p>
<pre>
    graft -pV weblint-1.017
</pre>
<p> You'd expect to see output similar to:</p>
<pre>
    Pruning      files in /usr/local which conflict with /usr/local/pkgs/weblint-1.017
    Processing   /usr/local/pkgs/weblint-1.017
    Processing   /usr/local/pkgs/weblint-1.017/man
    Processing   /usr/local/pkgs/weblint-1.017/man/man1
    RENAME       /usr/local/man/man1/weblint.1
    Processing   /usr/local/pkgs/weblint-1.017/bin
    RENAME       /usr/local/bin/weblint
    Processing   /usr/local/pkgs/weblint-1.017/lib
    RENAME       /usr/local/lib/global.weblintrc
</pre>
<p> If you elected to delete conflicting files instead of renaming them
 you'd use:</p>
<pre>
    graft -pDV weblint-1.017
</pre>
<p> and you'd see output similar to:</p>
<pre>
    Pruning      files in /usr/local which conflict with /usr/local/pkgs/weblint-1.017
    Processing   /usr/local/pkgs/weblint-1.017
    Processing   /usr/local/pkgs/weblint-1.017/man
    Processing   /usr/local/pkgs/weblint-1.017/man/man1
    UNLINK       /usr/local/man/man1/weblint.1
    Processing   /usr/local/pkgs/weblint-1.017/bin
    UNLINK       /usr/local/bin/weblint
    Processing   /usr/local/pkgs/weblint-1.017/lib
    UNLINK       /usr/local/lib/global.weblintrc
</pre>
<p> Now the new version of<em> weblint</em> 1.017 can be<em> grafted</em>
 in place:</p>
<pre>
    graft -i weblint-1.017
</pre>
<p> The<em> grafted</em> version of<em> weblint</em> can now be tested.</p>
<p> If we renamed conflicting files, they can be removed once the<em>
 grafted</em><em> weblint</em> has been satisfactorily tested:</p>
<pre>
    rm /usr/local/man/man1/weblint.1.pruned
    rm /usr/local/bin/weblint.pruned
    rm /usr/local/lib/global.weblintrc.pruned
</pre>
<hr width="25%">
<h3><a name="conflicts">Conflict Processing</a></h3>
<p> Occasionally<em> Graft</em> will fail to completely install a
 package. This occurs because<em> Graft</em> encounters a conflict. A
 conflict is defined as one of the following possibilities:</p>
<center>
<table border="2" cellpadding="3" summary="Conflcits">
<tr><th> Package Object</th><th> Target Object</th></tr>
<tr><td> directory</td><td> not a directory</td></tr>
<tr><td> file</td><td> directory</td></tr>
<tr><td> file</td><td> file</td></tr>
<tr><td> file</td><td> symbolic link to something other than the package
 object</td></tr>
</table>
</center>
<p> If<em> Graft</em> encounters such a conflict during the installation
 of a package it will report the conflict and exit.</p>
<p> Resolving the conflict depends on the nature of the conflict and is
 beyond the scope of this discussion - however most conflicts will
 either be the result of attempting to<em> graft</em> a package on top
 of the same package actually installed in the target directory or a
 file name clash between two (or more) different packages.</p>
<p> Conflicts arising from the pre-existence of a package in the target
 directory can be resolved using<em> graft</em>'s prune mechanism
 described above in <a href="#transitioning">&quot;Transitioning a package to<em>
 Graft</em> control&quot;</a>.</p>
<p> File name clash conflicts can be resolved by the use of either a <a href="#bypass">
<tt>.nograft</tt></a> or <a href="#exclude"><tt>.graft-exclude</tt></a>
 file or by<em> grafting</em> only part of a package as described above
 in <a href="#partial-graft">&quot;Grafting part of a package&quot;</a>.</p>
<p> If<em> Graft</em> encounters a conflict while deleting a package, it
 will report the conflict and continue deleting the remainder of the
 package. In this way<em> Graft</em> will delete as much of the package
 as possible. Conflicts that arise during deletion will probably be the
 result of an incorrectly installed package or the installation of other
 components of the same package without the use of<em> Graft</em>.</p>
<p> Conflict messages are written to standard error. All other messages
 are written to standard output. To quickly determine if a package will
 have any conflicts when<em> grafted</em>, redirect standard output to <tt>
/dev/null</tt></p>
<pre>
    graft -i -n <em>package</em> &gt; /dev/null
</pre>
<p> If you don't see any output then you can safely assume that there
 will be no conflicts when<em> grafting</em> this package.</p>
<p> See the comprehensive table above describing how <a href="#precedence">
conflicts are handled</a> for more details.</p>
<hr width="25%">
<h3><a name="exitstatus">Exit Status</a></h3>
<p><em> Graft</em> will terminate with an exit status of either 0, 1, 2,
 3 or 4 under the following conditions:</p>
<center>
<table border="2" cellpadding="3" summary="Exit Status">
<tr><th> Exit Status</th><th> Condition</th></tr>
<tr><td>
<center><strong> 0</strong></center>
</td><td> All operations succeeded.</td></tr>
<tr><td>
<center><strong> 1</strong></center>
</td><td> A conflict occurred during installation.</td></tr>
<tr><td>
<center><strong> 2</strong></center>
</td><td> Command line syntax was incorrect.</td></tr>
<tr><td>
<center><strong> 3</strong></center>
</td><td> One or more packages listed on the command line does not
 exist. Other valid packages listed on the command line were processed
 correctly.</td></tr>
<tr><td>
<center><strong> 4</strong></center>
</td><td> The log file <tt>/var/log/graft</tt> could not be updated.
 Usually a result of a permission error. Any other error condition will
 override this condition.</td></tr>
</table>
</center>
<hr>
<h2><a name="other-pkg-tools">Using<em> Graft</em> with other package
 management tools</a></h2>
<p> Most Unix vendors have released their own package management tools
 with their operating systems. Examples of this are Solaris 2.<em>x</em>
 with its<em> SVR4 Package Manager</em> <tt>pkgadd</tt>, RedHat Linux
 with its<em> RedHat Package Manager</em> <tt>rpm</tt>, Ubuntu Linux
 (and other Debian Linux derivatives) with its <tt>dpkg</tt> system and
 HP-UX 10.<em>x</em> with its <tt>swinstall</tt> suite.<em> Graft</em>
 has been designed as an adjunct to these package managers rather than a
 competitor. The author has used<em> Graft</em> successfully with all of
 the operating systems mentioned here.</p>
<ul>
<li>
<p> Many useful packages available in the public domain and from other
 commercial sources are not shipped with most flavours of Unix.<em>
 Graft</em> can be used to maintain a rich package environment beyond
 the set of packages provided by your vendor. Vendor based packages can
 still be maintained using the vendor's tools and<em> Graft</em> can be
 used to maintain your own packages.</p>
</li>
<li>
<p> The vendor based management tools are usually used to maintain
 single instances of a package on each machine. It is often difficult to
 have multiple versions of the same package coexisting on the same
 machine.<em> Graft</em> can be used to maintain multiple versions of a
 package to support legacy, production and development requirements
 simultaneously.</p>
</li>
<li>
<p> Another common problem with vendor supplied software is the speed at
 which upgrades are available. The large vendors are not known for
 providing quick fixes to many of their packages. (Notable exceptions to
 this are the vendors of operating systems based on open source software
 who can draw on the enormous number of users who submit patches because
 the source code is available). Using<em> Graft</em> you can obtain a
 working public domain version of a package (if one exists of course)
 and install it in a different location to the vendor copy. When the
 vendor releases a new version of the package, it can be installed using
 the vendor's package management tool and your<em> grafted</em> copy can
 be removed (only if the vendor's version of the package is better than
 the public domain version).</p>
</li>
<li>
<p> Sometimes, a vendor's package doesn't quite perform in the manner
 you'd like. It may be making assumptions about your file system(s) that
 are incorrect for your environment or it may not have all the features
 you'd like. If an alternative package is available - either in the
 public domain or from other commercial sources - it can be installed
 and<em> grafted</em> accordingly.</p>
</li>
</ul>
<hr>
<h2><a name="availability">Availability</a></h2>
<p> The latest version of<em> Graft</em> should always be available
 from:</p>
<pre>
    <a href="http://peters.gormand.com.au/Home/tools/graft">http://peters.gormand.com.au/Home/tools/graft</a>
</pre>
<hr>
<h2><a name="license">License</a></h2>
<p><em> Graft</em> is licensed under the terms of the GNU General Public
 License, Version 2, June 1991.</p>
<p> You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software Foundation,
 Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA, or
 download it from the Free Software Foundation's web site:</p>
<pre>
    <a href="http://www.gnu.org/copyleft/gpl.html">http://www.gnu.org/copyleft/gpl.html</a>
    <a href="http://www.gnu.org/copyleft/gpl.txt">http://www.gnu.org/copyleft/gpl.txt</a>
</pre>
<hr>
<!-- html code generated by txt2tags 2.6. (http://txt2tags.org) -->

<!-- cmdline: txt2tags -t html pkgmanagement.t2t -->
<HR NOSHADE>
<A HREF="index.html">Contents</A>
<A HREF="configuration.html">Previous</A>
</BODY>
</HTML>
